大多数情况下,JavaScript 应用需要处理信息。这有两个例子:

  1. 一个网上商店 —— 这里的信息可能包含正在售卖的商品和购物车
  2. 一个聊天应用 —— 这里的信息可能包括用户、消息等等。

变量就是用来储存这些信息的。

一个变量

一个 变量 是数据的“命名存储”。我们可以使用变量来保存商品、访客和其他信息。

在 JavaScript 中创建一个变量,我们需要用到 let 关键字。

下面的语句创建(换句话说,声明或者定义)了一个名称为“message”的变量:

let message;

现在,通过赋值操作符 = 为变量添加一些数据:

let message;

message = 'Hello'; // 保存字符串

该字符串目前保存到与该变量相关联的内存区域,可以通过使用变量名称访问它:

let message;
message = 'Hello!';

alert(message); // 显示变量内容

简洁一点,我们将变量定义和赋值合并成一行:

let message = 'Hello!'; // 定义变量,并且赋值

alert(message); // Hello!

也可以在一行中声明多个变量。

let user = 'John', age = 25, message = 'Hello';

看上去代码长度更短,但并不推荐。为了更好的可读性,请一行声明一个变量。

多行变量声明有点长,但更容易阅读:

let user = 'John';
let age = 25;
let message = 'Hello';

一些程序员采用下面的形式书写多个变量:

let user = 'John',
  age = 25,
  message = 'Hello';

……甚至使用“逗号优先”的形式:

let user = 'John'
  , age = 25
  , message = 'Hello';

技术上讲,这些变体都有一样的效果。所以,这是个个人品味和审美方面的问题。

var 而不是 let

在较旧的脚本中,你也可能发现另一个关键字 var,而不是 let:

var message = 'Hello';

var 关键字与 let 大体相同,也用来声明变量,但稍微有些不同,也有点“老派”。

letvar 之间有些微妙的差别,但目前对于我们来说并不重要。我们将会在 旧时的 "var" 章节中介绍它们。

一个现实生活的类比

如果将变量想象成一个“数据”的盒子,盒子上有一个唯一的标注盒子名字的贴纸。这样我们能更轻松地掌握“变量”的概念。

例如,变量 message 可以被想象成一个标有 "message" 的盒子,在盒子里面,有一个值为 "Hello!"

我们可以在盒子内放入任何值。

同样,我们也可以改变它。值可以根据需要多次改变:

let message;

message = 'Hello!';

message = 'World!'; // 值改变了

alert(message);

当值改变的时候,先前的数据就从变量中删除了。

还可以声明两个变量,然后将其中一个变量的数据拷贝进另一个变量。

let hello = 'Hello world!';

let message;

// 将字符串 'Hello world' 从变量 hello 拷贝进 message
message = hello;

// 现在两个变量保存着相同的数据
alert(hello); // Hello world!
alert(message); // Hello world!
函数式语言

有趣的是,也存在禁止更改变量值的函数式编程语言。比如,Scala 或者 Erlang

在这种类型的语言中,一旦值保存在盒子中,就永远存在。如果你试图保存其他值,它会强制创建一个新盒子(声明一个新变量),无法重用先前的变量。

虽然第一次看上去有点奇怪,但是这些语言有很大的发展潜力。不仅如此,在某些领域,比如并行计算,这个限制有一定的好处。研究这样的一门语言(即使不打算很快就用上它)有助于开阔视野。

变量命名

JavaScript 的变量命名有两个限制:

  1. 变量名称必须仅包含字母,数字,符号 $_
  2. 首字符必须非数字。

有效的命名,例如:

let userName;
let test123;

如果命名包括多个单词,通常采用驼峰式命名法(camelCase)。也就是,单词一个接一个,每个单词以大写字母开头:myVeryLongName

有趣的是,美元符号 '$' 和下划线 '_' 也可以在命名中使用。它们是正常的符号,就跟字母一样,没有任何特殊的含义。

下面的命名是有效的:

let $ = 1; // 使用 "$" 来声明一个变量
let _ = 2; // 现在是用 "_" 来声明一个变量

alert($ + _); // 3

下面的变量命名不正确:

let 1a; // 不能以数字开始

let my-name; // 连字符 '-' 不允许在命名中出现
区分大小写

命名为 appleAppLE 的变量是不同的两个变量。

允许非英文字母,但不推荐

可以使用任何语言,包括西里尔字母(cyrillic letters)甚至是象形文字,就像这样:

let имя = '...';
let 我 = '...';

技术上讲,完全没有错误,这样的命名是完全允许的,但是有一个国际传统:在变量命名中使用英文。哪怕我们正在写一个很小的脚本,它也有可能有很长的生命周期。某个时候,来自其他国家的人可能会阅读它。

保留字

有一张保留字列表无法用作变量命名,因为它们被语言本身采用了。

比如,单词 letclassreturnfunction 被保留。

下面的代码将会抛出一个语法错误:

let let = 5; // 不能用 "let" 来命名一个变量,错误!
let return = 5; // 同样,不能使用 "return",错误!
未采用 use strict 下的赋值

一般,需要在使用一个变量前定义它。但是在旧时代,可以简单地赋值来创建一个变量,而不需要 let。如果不使用 use strict,这仍然正常工作,这种行为是为了保持与旧脚本的兼容。

// 注意:这个例子中没有 "use strict"

num = 5; // 如果变量 "num" 不存在,就会被创建

alert(num); // 5

这是个糟糕的做法,严格模式下会抛出错误。

"use strict";

num = 5; // error: num is not defined

常量

声明一个常数(不变)变量,可以使用 const 而非 let

const myBirthday = '18.04.1982';

使用 const 声明的变量称为“常量”。它们不能被修改,尝试这样做就会造成错误:

const myBirthday = '18.04.1982';

myBirthday = '01.01.2001'; // 错误,不能对常量重新赋值

当程序员能确定这个变量永远不会改变的时候,就可以使用 const 来确保这种行为,并且清楚地向别人传递这一事实。

大写形式的常数

一个普遍的做法是将常量用作别名,以便记住那些在执行之前就已知的难以记住的值。

这些常量使用大写和下划线命名。

例如,让我们以所谓“web”(十六进制)的格式为颜色声明常量:

const COLOR_RED = "#F00";
const COLOR_GREEN = "#0F0";
const COLOR_BLUE = "#00F";
const COLOR_ORANGE = "#FF7F00";

// ...当需要选择一个颜色
let color = COLOR_ORANGE;
alert(color); // #FF7F00

好处:

  • COLOR_ORANGE"#FF7F00" 更容易记忆。
  • 比起 COLOR_ORANGE 而言,"#FF7F00" 更容易输错。
  • 阅读代码时,COLOR_ORANGE#FF7F00 更有含义。

什么时候该为常量使用大写命名,什么时候常规命名?让我们弄清楚一点:

作为一个“常数”,意味着值永远不变。但是有些常量在执行之前就已知了(比如红色的十六进制值),还有些在执行期间被“计算”出来,但初始赋值之后就不会改变。

例如:

const pageLoadTime = /* time taken by a webpage to load */;

pageLoadTime 的值在页面加载之前是未知的,所以采用常规命名。但是它仍然是个常量,因为赋值之后不会改变。

换句话说,大写命名的常量仅用作“硬编码”值的别名。

正确命名变量

谈到变量,还有一件非常重要的事。

一个变量名应该有一个清晰、明显的含义,描述了它存储的数据。

变量命名是编程过程中最重要和最复杂的技能之一。快速地浏览变量的命名就知道代码是一个初学者还是有经验的开发者书写的。

在一个现实的项目中,大多数的时间用来修改和扩展现有的代码库,而不是从头开始写一些完全独立的代码。当一段时间后,我们做完其他事情,重返我们的代码,找到命名良好的信息要容易得多。换句话说,变量要有个好名字。

声明变量之前,多花点时间思考它的良好命名。你会受益良多。

一些很好遵循的规则是:

  • 使用人类可读的命名,比如 userName 或者 shoppingCart
  • 诸如 abc 的缩写和短名称,离它们远点,除非你真的知道你在干什么。
  • 变量名要能够准确描述变量并且足够简洁。不好的例子就是 datavalue,这样的名称等于什么都没说。如果能够非常明显地从上下文知道数据和值所表达的含义,这样使用它们也是可以的。
  • 脑海中的术语和团队保持一致。如果站点的访客称为“用户”,则我们采用相关的变量命名,比如 currentUser 或者 newUser,而不要 currentVisitor 或者一个 newManInTown

听上去很简单?确实如此,但是在实践中选择一个一目了然的变量名称并非如此。大胆试试吧。

重用还是新建?

最后一点,有一些懒惰的程序员,倾向于重用现有的变量,而不是声明一个新的变量。

结果是,这个变量就像是被扔进不同东西盒子,而没有改变它的贴纸。现在里面是什么?谁知道呢。我们需要靠近一点,然后检查它。

这样的程序员节省了一点变量声明的时间,但却在调试代码的时候损失数十倍时间。

额外声明一个变量绝对是利大于弊的。

目前的 JavaScript 压缩器和浏览器都很够很好地优化代码,所以不会产生性能问题。为不同的值使用不同的变量可以帮助引擎进行优化。

总结

我们可以声明变量来存储数据。可以通过使用 varlet 或者 const 来完成。

  • let – 新时代的变量声明方式。Chrome(V8)中代码必须开启严格模式以使用 let
  • var – 旧时代的变量声明方式。一般情况下,我们不会使用它。但是,我们会在 旧时的 "var" 章节介绍 varlet 的微妙差别,以防你需要它们。
  • const – 类似于let,但是变量的值无法被修改。

变量应当以一种容易理解变量内部是什么的方式进行命名。

任务

重要程度: 2
  1. 声明两个变量:adminname
  2. 将值 "John" 赋给 name
  3. name 变量中拷贝其值给 admin
  4. 使用 alert 显示 admin 的值(一定会输出 “John”)。

下面的代码,每一行都对应着任务列表中的对应项。

let admin, name; // 一次声明两个变量。

name = "John";

admin = name;

alert( admin ); // "John"
重要程度: 3
  1. 使用我们的星球的名字创建一个变量。你会怎么命名这个变量?
  2. 创建一个变量来存储当前浏览者的名字。你会怎么命名这个变量?

首先,声明变量代表我们星球的名字。

这很简单:

let ourPlanetName = "Earth";

注意,我们也可以用一个更短的名字 planet,但是它可能并不清楚它指的是什么行星。再啰嗦一点也是挺好的。至少直到这个变量“不太长”就行。

第二,定义当前浏览者的名字:

let currentUserName = "John";

还有,如果我们的确知道用户就是当前的用户的话,我们可以使用更短的 userName

现代编辑器的自动补全可以让长变量名变得容易书写。不要浪费这个特性。一个名字中包含三个词就挺好的。

如果你的编辑器没有合适的自动补全,换一个新的吧

重要程度: 4

检查下面的代码:

const birthday = '18.04.1982';

const age = someCode(birthday);

这里我们有一个 birthday 日期常量和通过一些有用的代码(为了保持简短这里没有提供,并且细节也无关紧要)从 birthday 计算出的 age 常量。

对于 birthday 使用大写方式正确吗?那么 age 呢?或者两者?

const BIRTHDAY = '18.04.1982'; // 使用大写?

const AGE = someCode(BIRTHDAY); // 使用大写?

我们通常用大写字母表示“硬编码”的常量。或者,换句话说,当值在执行之前被知道并直接写入代码中的时候。

在这个代码中 birthday 确信是这样的。因此我们可以使用大写。

在对照组中,age 是在运行时计算出的。今天我们有一个年龄,一年以后我们就会有另一个。它在某种意义上不会通过代码的执行而改变。但是相比 birthday 它是“少一些常量”的,它是计算出的,因此我们应该使用小写。

教程路线图

评论

在评论之前先阅读本内容…
  • 欢迎你在文章下添加补充内容、提出你的问题或回答提出的问题。
  • 使用 <code> 标签插入几行代码,对于多行代码 — 可以使用 <pre>,对于超过十行的代码 — 建议使用沙箱(plnkrJSBincodepen 等)。
  • 如果你无法理解文章中的内容 — 请详细说明。