大多数情况下,JavaScript 应用都是在处理信息。举两个例子:

  1. 网上商城——包括一些要出售的商品和购物车的信息。
  2. 聊天程序——包括用户、消息等一些信息。

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

变量

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

译注:这里讲的“命名存储”,是指在内存中开辟了一小块区域用于存储数据,这块区域用变量名标识,之后我们可以使用这个变量名来读到这块特定区域里存储的数据。

在 JavaScript 中创建变量使用关键字 let

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

  1. let message;

我们可以通过赋值运算符 = 来给这个变量赋一个值:

  1. let message;
  2. message = 'Hello'; // 变量中存储了一个字符串

字符串现在被保存到与该变量相关联的内存区域中,我们可以使用变量名来访问它:

  1. let message;
  2. message = 'Hello!';
  3. alert(message); // 显示变量内容

简单起见,我们可以将变量声明和赋值合并成一行:

  1. let message = 'Hello!'; // 定义变量并赋值
  2. alert(message); // Hello!

也可以在一行中同时声明多个变量:

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

这种写法更加简短,但不推荐。为了提高可读性,应该每一个变量声明独处一行。

多行变量声明写法稍微长一点,但更容易阅读:

  1. let user = 'John';
  2. let age = 25;
  3. let message = 'Hello';

有些人也会这样写:

  1. let user = 'John',
  2. age = 25,
  3. message = 'Hello';

甚至是写成“逗号优先”风格:

  1. let user = 'John'
  2. , age = 25
  3. , message = 'Hello';

从技术上讲,所有这些变体效果一样。所以,这是一个关于个人品味和美学的问题。

⚠️旧脚本变量声明 var

在旧脚本中,您还可以找到另一个关键字:var 而不是 let。

  1. var message = 'Hello';

var 关键字几乎等同于 let。也用于声明变量,但有一点不同——“旧式”的行为表现。

var 和 let 之间有些细微的差别,但以后变得不再重要,我们稍后会在《“旧式”var 声明》一章里详细介绍。

真实类比

如果把变量想象成装数据的“盒子”,会更容易理解。

举个例子,可以把变量 message 可以想象成是一个标记 “message” 的盒子,它装有一个值 “Hello!”:

变量 - 图1

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

一个值也可以根据需要多次修改:

  1. let message;
  2. message = 'Hello!';
  3. message = 'World!'; // 值发生了变化
  4. alert(message);

当值发生变化时,旧值将从变量中删除:

变量 - 图2

我们也可以声明两个变量,并将数据从一个变量复制到另一个。

  1. let hello = 'Hello world!';
  2. let message;
  3. // 将变量 hello 的值 'Hello world' 复制到 message
  4. message = hello;
  5. // 现在两个变量的值一样
  6. alert(hello); // Hello world!
  7. alert(message); // Hello world!

⚠️函数式语言

有趣的是,还存在一些 函数式 编程语言,它们禁止改变变量值。比如 ScalaErlang

在这种语言中,一旦值被存储在“盒子”中,它就永远存在。如果我们需要存储其他值,语言会强制创建一个新盒子(声明一个新变量),不能再用旧的了。

虽然乍一看可能有点奇怪,但这些语言都有很强的发展能力。更重要的是,在一些领域,比如并行计算,这种限制带来了一定的好处。研究这样一种语言(即使不打算很快使用它)也能帮助我们扩展下思维。

变量命名

在 JavaScript 中,变量名有两个限制:

  1. 变量名仅能包含字母、数字和符号 $_
  2. 第一个字符不能是数字

下面列举了一些有效的变量名:

  1. let userName;
  2. let test123;

当一个变量名中包含多个单词时,一般使用驼峰命名(camelCase)法。也就是说,名称中每个单词的首字母大写(除第一个),比如 myVeryLongName

有趣的是,美元符号 "$" 和下划线 "_" 也可以用在变量名中。它们是普通的符号,就像字母一样,没有任何特殊的意义。

这些名字是有效的:

  1. let $ = 1; // 声明一个变量 "$"
  2. let _ = 2; // 声明一个变量 "_"
  3. alert($ + _); // 3

错误的变量命名:

  1. let 1a; // 不能以数字开头
  2. let my-name; // 中划线 '-' 也是不允许的

⚠️大小写敏感

变量名 apple 和 Apple 是两个不同的变量名。

⚠️非英语字母是允许的,但不推荐

可以使用任何语言的字符,包括西里尔字母、甚至是象形文字:

  1. let имя = '...';
  2. let = '...';

技术上讲,并没错,这样的命名是允许的,但使用英文命名变量是国际上约定的习惯。即使我们在写一个小脚本,它也可能有很长的寿命,来自其他国家的人可能需要花一些时间才能读懂。

⚠️保留字

有一个保留字的清单,是不能用作变量名的,因为它们被语言本身使用了。

例如,单词 letclassreturnfunction 这些都是保留字。

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

  1. let let = 5; // 不能将变量名声明为 "let", 会出错!
  2. let return = 5; // 也不能将变量名起为 "return", 会出错!

⚠️不带 use strict 的赋值

通常,我们需要在使用变量之前定义一个变量。但是在旧时代,仅通过赋值就能创建一个变量,当然,这是在未启用严格模式的情况下。这种行为是为了兼容旧脚本而保留的。

  1. // note: no "use strict" in this example
  2. num = 5; // the variable "num" is created if didn't exist
  3. alert(num); // 5

这是一个不好的做法,严格模式下会抛出错误:

  1. "use strict";
  2. num = 5; // error: num is not defined

常量

声明一个常量(不变的)变量,要使用 const 而不是 let

  1. const myBirthday = '18.04.1982';

使用 const 声明的变量称为“常量”,它们不能被改变。尝试修改会产生错误:

  1. const myBirthday = '18.04.1982';
  2. myBirthday = '01.01.2001'; // error, can't reassign the constant!

当开发人员确定这个变量不会再改变时,可以使用 const,并且别人也能清晰地知道。

大写形式的常量

有一种普遍的做法是使用常量作为难以记住的值的别名,这些值在代码运行前就已知。

这些常量用大写字母 + 下划线来命名。

  1. const COLOR_RED = "#F00";
  2. const COLOR_GREEN = "#0F0";
  3. const COLOR_BLUE = "#00F";
  4. const COLOR_ORANGE = "#FF7F00";
  5. // ...当需要获取一个颜色的时候
  6. let color = COLOR_ORANGE;
  7. alert(color); // #FF7F00

好处:

  • COLOR_ORANGE 比 “#FF7F00” 更好记
  • “#FF7F00” 比 COLOR_ORANGE 更容易录入错误。
  • COLOR_ORANGE 比 “#FF7F00” 更有可读性。

我们什么时候应该用大写字母来表示一个常量,什么时候使用常量?

“常量”意味着它的值永远不会改变。但是在运行之前就已知的常量,还有一些是在运行时计算出来的,分配之后不会改变。

例如:

  1. const pageLoadTime = /* 网页加载耗时 */;

页面加载之前不知道 pageLoadTime 的值,所以它的命名是正常的。但它仍然是一个常数,因为它在赋值后不会改变。

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

正确命名

说到变量,还有一个非常重要的东西——请合理地命名变量。如果需要的话,花点时间思考。

变量命名是编程中最重要和最复杂的技能之一。快速浏览一下变量名就可以发现哪些代码是由初学者编写的,哪些代码是由经验丰富的开发人员编写的。

在一个真实的项目中,大多数时间都花在修改和扩展现有的代码库上,而不是从头开始编写完全独立的代码。当我们在做其他事情再回来看代码时,理解有意义的命名要容易得多。

请在声明之前花些时间考虑变量的合适名称,会让你事半功倍。

一些好的习惯是:

  • 使用可读名称,比如 usernameshoppingCart
  • 远离缩写词或短名称,像 abc,除非你知道你在做什么
  • 使这个名字最大化地描述和简洁。坏的例子是 data,value。这样的名字什么也没说。如果从数据或值的上下文来看,使用它们是可以的
  • 在你的团队和你自己的思维里达成一致。如果一个站点访问者被称为“user”那么我们应该将相关变量像命名成 currentUsernewUser,而不是 currentVisitor 或者是 newManInTown

听起来很简单?确实如此,但在实践中创造出好的、具有描性格并且简洁的名称并没那么容易。现在就开始这么做吧。

⚠️重用已有变量还是创建常量?

最后一有个要注意的地方,有些懒惰的程序员,他们不喜欢声明新变量,而是倾向于重用现有的变量。

因此,这个变量就像一个潘多拉盒子,里面是什么?谁也不知道,需要人工去确认。

虽然在声明变量的功夫上节省了一点时间和精力,但在调试代码时却要付出十倍的代价。

额外的变量声明是好的,而不是邪恶的。

现代的 JavaScript 代码压缩工具以及浏览器自身对运行代码的优化,已经很大部分的减少了性能问题。为不同的值使用不同的变量甚至可以帮助引擎优化。

总结

我们使用 varletconst 关键字声明变量、存储数据。

  • let:新式变量声明方式。
  • var:旧式变量声明方式。正常情况下不会使用它,我们会在《旧式变量声明方式“var”》一章中介绍它与 let 的区别,帮助你辨别不得已使用它的场景。
  • const:类似 let,但使用它声明的变量,值是不能修改的。

还有,给变量命名的时候,应该起一个大家都能看懂的名字。

(完)


📄 文档信息

🕘 更新时间:2021/09/18
🔗 原文链接:https://javascript.info/variables