变量是许多编程语言的基本组成部分, 也是新手需要学习的第一个也是最重要的概念. JavaScript 中有许多不同的变量属性, 以及命名变量时必须遵循的一些规则. 在 JavaScript 中, 有三个关键字用于声明变量 --var,let 和 const-- 每个关键字都会影响代码对变量的不同解释.
本教程将介绍什么是变量, 如何声明和命名变量, 并进一步研究 var,let 和 const 之间的区别. 我们还将回顾提升的影响以及全局和局部作用域对变量行为的重要性.
理解变量
变量是用于存储值的命名容器. 我们可能多次引用的一条信息可以存储在一个变量中, 供以后使用或修改. 在 JavaScript 中, 变量中包含的值可以是任何 JavaScript 数据类型, 包括数字, 字符串或对象.
在今天的 JavaScript 所基于的 ECMAScript 2015 (ES6)语言规范之前, 只有一种方法来声明变量 -- 使用 var 关键字. 因此, 大多数较老的代码和学习资源将只对变量使用 var. 我们将在下面单独一节讨论 var,let 和 const 关键字之间的区别.
我们可以使用 var 来演示变量本身的概念. 在下面的示例中, 我们将声明一个变量, 并为其赋值.
- // Assign the string value Sammy to the username identifier
- var username = "sammy_shark";
本声明由以下几部分组成:
使用 var 关键字声明变量
变量名(或标识符), 用户名
赋值操作, 由 = 语法表示
分配的值 "sammy_shark"
现在我们可以在代码中使用 username.JavaScript 将记住 username 表示字符串值 sammy_shark.
- // Check if variable is equal to value
- if (username === "sammy_shark") {
- console.log(true);
- }
输出:
true
如前所述, 变量可以用来表示任何 JavaScript 数据类型. 在本例中, 我们将使用字符串, 数字, 对象, 布尔值和 null 值声明变量.
- // Assignment of various variables
- var name = "Sammy";
- var spartans = 300;
- var kingdoms = [ "mammals", "birds", "fish" ];
- var poem = {
- roses: "red", violets: "blue"
- };
- var success = true;
- var nothing = null;
使用 console.log, 我们可以看到特定变量中包含的值.
- // Send spartans variable to the console
- console.log(spartans);
输出: 300
变量将数据存储在内存中, 稍后可以访问和修改这些数据. 变量也可以重新分配, 并给定一个新值. 下面的简化示例演示了如何将密码存储到变量中, 然后进行更新.
- // 为 password 变量赋值
- var password = "hunter2";
- // 用一个新值重新分配变量值
- password = "hunter3";
- console.log(password);
输出:
'hunter3'
在实际的程序中, 密码很可能安全地存储在数据库中. 然而, 这个例子说明了一种情况, 在这种情况下, 我们可能需要更新变量的值. password 的值是 hunter2, 但是我们将其重新分配给了 hunter3, 这是 JavaScript 从那时起可以识别的值.
命名变量
变量名在 JavaScript 中称为标识符. 我们讨论了在理解 JavaScript 语法和代码结构时命名标识符的一些规则, 总结如下:
变量名只能由字母 (a-z), 数字(0-9), 美元符号($) 和下划线 (_) 组成
变量名不能包含任何空白字符(制表符或空格)
数字不能是任何变量的名称开头
保留的关键字不能用作变量的名称
变量名区分大小写
JavaScript 还习惯在使用 var 或 let 声明的函数和变量的名称中使用驼峰大小写(有时作为驼峰大小写进行样式化). 这是一种将第一个单词小写, 然后将后面每个单词的第一个字母大写, 中间没有空格的做法. 除了一些例外, 大多数非常量的变量都遵循这种约定. 使用 const 关键字声明的常量变量的名称通常都是大写的.
这可能看起来像要学习很多规则, 但很快就会成为编写有效和常规变量名称的第二天性.
var,let 和 const 之间的区别
JavaScript 有三个不同的关键字来声明变量, 这给语言增加了额外的复杂性. 三者之间的区别是基于范围, 提升和重新分配.
关键字 < br ztid="96" ow="0" oh="0"> | 范围 | 变量提升 | 可以重新分配 | 可以重新定义 |
---|---|---|---|---|
var | 功能范围 | Yes | Yes | Yes |
let | 阻止范围 | No | Yes | No |
const | 阻止范围 | No | No | No |
您可能想知道应该在自己的程序中使用这三种方法中的哪一种. 一个普遍接受的做法是尽可能多地使用 const, 并在循环和重新分配的情况下使用 let. 通常, 在处理遗留代码之外可以避免 var.
变量作用域
JavaScript 中的作用域是指代码的当前上下文, 它决定了变量对 JavaScript 的可访问性. 范围的两种类型是局部的和全局的:
全局变量是在块之外声明的变量
局部变量是在块内声明的变量
在下面的示例中, 我们将创建一个全局变量.
- // 初始化一个全局变量
- var creature = "wolf";
我们知道变量可以重新分配. 使用局部作用域, 我们实际上可以创建与外部作用域中的变量同名的新变量, 而无需更改或重新分配原始值.
在下面的示例中, 我们将创建一个全局 species 变量. 函数内部是一个具有相同名称的局部变量. 通过将它们发送到控制台, 我们可以看到变量的值如何根据范围而不同, 并且原始值不会更改.
- // 初始化一个全局变量
- var species = "human";
- function transform() {
- // 初始化一个局部的, 函数作用域的变量
- var species = "werewolf";
- console.log(species);
- }
- // 记录全局和局部变量
- console.log(species);
- transform();
- console.log(species);
输出:
- human
- werewolf
- human
在本例中, 局部变量是函数作用域的. 使用 var 关键字声明的变量总是函数作用域, 这意味着它们将函数识别为具有独立作用域. 因此, 这个局部作用域的变量不能从全局作用域访问.
然而, 新的关键字 let 和 const 是块范围的. 这意味着从任何类型的块 (包括函数块, if 语句, for 和 while 循环) 创建一个新的本地范围.
为了说明函数作用域变量和块作用域变量之间的区别, 我们将使用 let 在 if 块中分配一个新变量.
- var fullMoon = true;
- // 初始化一个全局变量
- let species = "human";
- if (fullMoon) {
- // 初始化一个块范围的变量
- let species = "werewolf";
- console.log(`It is a full moon. Lupin is currently a ${species}.`);
- }
- console.log(`It is not a full moon. Lupin is currently a ${species}.`);
输出:
- It is a full moon. Lupin is currently a werewolf.
- It is not a full moon. Lupin is currently a human.
在此示例中, species 变量具有一个值 global(human), 另一个值 local(werewolf).var 但是, 如果我们使用, 则会有不同的结果.
- // 使用 var 初始化一个变量
- var species = "human";
- if (fullMoon) {
- // 尝试在一个块中创建一个新变量
- var species = "werewolf";
- console.log(`It is a full moon. Lupin is currently a ${species}.`);
- }
- console.log(`It is not a full moon. Lupin is currently a ${species}.`);
输出:
- It is a full moon. Lupin is currently a werewolf.
- It is not a full moon. Lupin is currently a werewolf.
在这个例子的结果中, 全局变量和块范围的变量都以相同的值结束. 这是因为您不是使用 var 创建一个新的本地变量, 而是在相同的范围内重新分配相同的变量. var 不能识别是否属于不同的新范围. 通常建议声明块范围的变量, 因为它们生成的代码不太可能无意中覆盖变量值.
变量提升
到目前为止, 在大多数示例中, 我们已经使用 var 声明了一个变量, 并使用一个值初始化了它. 在声明和初始化之后, 我们可以访问或重新分配变量.
如果我们试图在变量被声明和初始化之前使用它, 它将返回 undefined.
- // 在声明变量之前尝试使用它
- console.log(x);
/ / 变量赋值
var x = 100;
输出:
undefined
但是, 如果省略 var 关键字, 就不再声明变量, 而是初始化它. 它将返回一个 ReferenceError 并停止脚本的执行.
- // 在声明变量之前尝试使用它
- console.log(x);
- // 没有 var 的变量赋值
- x = 100;
输出:
ReferenceError: x is not defined
原因在于提升, 这是 JavaScript 的一种行为, 其中变量和函数声明被移到它们作用域的顶部. 由于只挂起实际声明, 而没有初始化, 因此第一个示例中的值返回未定义的值.
为了更清楚地演示这个概念, 下面是我们编写的代码以及 JavaScript 如何解释它.
- // The code we wrote
- console.log(x);
- var x = 100;
- // How JavaScript interpreted it
- var x;
- console.log(x);
- x = 100;
JavaScript 在执行脚本之前将 x 保存为内存作为变量. 由于它在定义之前仍然被调用, 因此结果是未定义的而不是 100. 但是, 它不会导致 ReferenceError 并停止脚本.
尽管 var 关键字实际上并未更改 var 的位置, 但这有助于表示提升的工作原理. 但是, 这种行为可能会导致问题, 因为编写此代码的程序员可能希望 x 的输出为 true, 而不是 undefined.
在下一个例子中, 我们还可以看到提升是如何导致不可预测的结果的:
- // 在全局范围内初始化 x
- var x = 100;
- function hoist() {
- // 不应影响编码结果的条件
- if (false) {
- var x = 200;
- }
- console.log(x);
- }
- hoist();
输出:
undefined
在本例中, 我们声明 x 全局为 100. 根据 if 语句, x 可以更改为 200, 但是由于条件为 false, 所以它不应该影响 x 的值.
这种不可预测的行为可能会在程序中引起 bug. 由于 let 和 const 是块范围的, 所以它们不会以这种方式提升, 如下所示.
- // 在全局范围内初始化 x
- let x = true;function hoist() {
- // 在函数作用域中初始化 x
- if (3 === 4) {
- let x = false;
- }
- console.log(x);
- }
- hoist();
输出:
true
变量的重复声明 (这在 var 中是可能的) 将在 let 和 const 中抛出一个错误.
- // 试图覆盖用 var 声明的变量
- var x = 1;
- var x = 2;
- console.log(x);
输出: 2
- // 试图覆盖用 let 声明的变量
- let y = 1;
- let y = 2;
- console.log(y);
输出:
Uncaught SyntaxError: Identifier 'y' has already been declared
总之, 使用 var 引入的变量有可能受到提升的影响, 提升是 JavaScript 中的一种机制, 其中变量声明被保存到内存中. 这可能导致代码中出现未定义的变量. let 和 const 的引入解决了这个问题, 它在试图在声明变量之前使用该变量或多次声明该变量时抛出一个错误.
常量
许多编程语言都有常量, 这些常量是不能修改或更改的值. 在 JavaScript 中, const 标识符是根据常量建模的, 不能重新分配分配给 const 的值.
将所有 const 标识符都写成大写是常见的约定. 这将它们与其他变量值区分开来.
在下面的示例中, 我们使用 const 关键字将变量 SPECIES 初始化为常量. 试图重新分配变量将导致错误.
- // 给 const 赋值
- const SPECIES = "human";
- // 尝试重新分配值
- SPECIES = "werewolf";
- console.log(SPECIES);
输出:
Uncaught TypeError: Assignment to constant variable.
因为不能重新分配 const 值, 所以需要同时声明和初始化它们, 否则也会抛出错误.
- // 声明, 但不初始化 const
- const TODO;
- console.log(TODO);
输出:
Uncaught SyntaxError: Missing initializer in const declaration
不能在编程中更改的值称为不可变值, 而可以更改的值是可变的. 虽然 const 值不能重新分配, 但是它们是可变的, 因为可以修改用 const 声明的对象的属性.
- // 创建一个具有两个属性的 CAR 对象
- const CAR = {
- color: "blue",
- price: 15000}
- // 修改 CAR 的属性
- CAR.price = 20000;
- console.log(CAR);
输出:
{ color: 'blue', price: 20000 }
常量非常有用, 可以让将来的自己和其他程序员清楚地认识到, 不应该重新分配预期的变量. 如果您希望将来修改某个变量, 那么您可能希望使用 let 来声明该变量.
来源: http://www.css88.com/web/javascript/11403.html