变量是为值分配代表性名称的数据结构。 它们可以包含任何类型的数据。
变量的名称称为“标识符”。有效标识符必须遵循 这些规则:
- 标识符可以包含 Unicode 字母、美元符号 ($)、下划线 字符 (_)、数字 (0-9),甚至一些 Unicode 字符。
- 标识符不能包含空格,因为解析器会使用空格来
单独的输入元素。例如,如果您尝试调用一个变量,
my Variable
,而不是myVariable
,解析器会看到两个标识符:my
和Variable
,并抛出语法错误(“意外令牌: 标识符)。 标识符必须以字母、下划线 (
_
) 或美元符号 ($
) 开头。 不能以数字开头,以免将数字和 标识符:let 1a = true; > Uncaught SyntaxError: Invalid or unexpected token
如果 JavaScript 允许在标识符的开头使用数字,那么 只由数字组成的标识符,会导致用作 及用作身份识别号码的号码:
let 10 = 20 10 + 5 > ?
“保留字词” 语法上有意义的字词不能用作标识符。
标识符不能包含特殊字符 (
! . , / \ + - * =
)。
以下规则不是严格的标识符创建规则, 业界最佳实践,让代码维护变得更轻松。如果您的特定 项目具有不同的标准,请遵循这些标准以确保一致性。
按照 JavaScript 的内置方法和属性设置的示例, 驼峰式大小写(设计样式也为“camelCase”)是 由多个字词组成的标识符。驼峰式大小写是一种 除了第一个单词的首字母,将除第一个单词之外的每个单词的首字母都大写,以提升 可读性(不含空格)。
let camelCasedIdentifier = true;
有些项目会根据上下文和性质使用其他命名惯例 数据。例如,class 的第一个字母 通常采用大写形式,因此多字词类名称通常会使用驼峰 这种大小写形式通常称为“大驼峰式大小写”或 Pascal 大小写形式。
class MyClass {
}
标识符应简明扼要地描述它们所包含数据的性质(例如
例如,与 theNumberOfDaysInTheCurrentMonth
相比,currentMonthDays
这个名称更好)
并且一目了然(originalValue
比 val
更佳)。通过
本单元中使用的 myVariable
标识符
孤立的示例,但在生产代码中将毫无用处,因为它们
不会提供有关其所含数据的信息。
标识符所包含的数据不应过于具体
它们的值可能会根据脚本对这些数据的操作方式而变化,
决策和决策。例如,最初给定
标识符 miles
可能需要在稍后需要更改为以公里为单位的值,
项目,因此维护人员需要将对该变量的所有引用更改为
避免日后出现混淆为防止出现这种情况,请使用 distance
作为标识符
。
JavaScript 不会赋予标识符
以下划线字符 (_
) 开头,但通常用于显示
变量、方法或属性是“私有”的也就是说
在包含它的对象的上下文中使用,而不应是
可在该环境之外访问或修改。这是沿用而来的惯例
与其他编程语言不同,并且在 JavaScript 的
私有属性。
变量声明
有多种方法可以让 JavaScript 识别标识符,即一个进程,
名为“声明”变量。使用 let
、const
、
或 var
个关键字。
let myVariable;
使用 let
或 var
声明可以随时更改的变量。这些
关键字会告知 JavaScript 解释器,字符串是
可能含有值的标识符
使用现代代码库时,请使用 let
而不是 var
。var
仍可使用
但它也有一些非直观的行为,
最早的 JavaScript 版本,之后无法更改为
保留向后兼容性在 ES6 中添加了 let
,以解决一些问题
var
的设计
声明的变量通过为变量赋值来“初始化”。使用
单个等号 (=
) 来为变量赋值或为其重新赋值。您可以
作为声明它的同一语句的一部分:
let myVariable = 5;
myVariable + myVariable
> 10
您还可以使用 let
(或 var
)声明变量,而无需初始化变量
。如果这样做,该变量的初始值为 undefined
,直到
代码会为其分配一个值。
let myVariable;
myVariable;
> undefined
myVariable = 5;
myVariable + myVariable
> 10
值为 undefined
的变量与未定义变量不同
尚未声明其标识符的 ID。引用未引用的变量
会导致错误。
myVariable
> Uncaught ReferenceError: myVariable is not defined
let myVariable;
myVariable
> undefined
标识符与值之间的关联通常称为“绑定”。
遵循 let
、var
或 const
关键字的语法称为
“绑定列表”支持多个以英文逗号分隔的变量声明
(以预期的分号结尾)。这会使以下代码段
功能上完全相同:
let firstVariable,
secondVariable,
thirdVariable;
let firstVariable;
let secondVariable;
let thirdVariable;
重新赋值变量的值不使用 let
(或 var
),因为 JavaScript
已经知道该变量存在:
let myVariable = true;
myVariable
> true
myVariable = false;
myVariable
> false
您可以根据变量的现有值为它们重新分配新值:
let myVariable = 10;
myVariable
> 10
myVariable = myVariable * myVariable;
myVariable
> 100
如果您尝试在生产环境中使用 let
重新声明变量,
您会遇到语法错误:
let myVariable = true;
let myVariable = false;
> Uncaught SyntaxError: redeclaration of let myVariable
浏览器的开发者工具
更宽松的 let
(和 class
)重复声明,因此您可能
会在开发者控制台中看到同样的错误。
为了保持旧版浏览器的兼容性,var
允许进行不必要的重复声明
在任何情况下都不会出错:
var myVariable = true;
var myVariable = false;
myVariable\
> false
const
使用 const
关键字声明一个常量,该常量必须是
立即初始化,然后无法更改。常量标识符
遵循与使用 let
(以及 var
)声明的变量相同的规则:
const myConstant = true;
myConstant
> true
要声明常量,必须立即为其分配值,因为
在创建常量后就不能重新赋值,因此任何未初始化的
常量将永远保持 undefined
状态。如果您尝试声明一个常量
则会出现语法错误:
const myConstant;
Uncaught SyntaxError: missing = in const declaration
尝试按照您可能想要的方式更改使用 const
声明的变量的值
使用 let
(或 var
)更改声明的变量的值会导致类型
错误:
const myConstant = true;
myConstant = false;
> Uncaught TypeError: invalid assignment to const 'myConstant'
不过,当常量与对象关联时,该常量的属性将 对象可以更改的。
const constantObject = { "firstvalue" : true };
constantObject
> Object { firstvalue: true }
constantObject.secondvalue = false;
constantObject
> Object { firstvalue: true, secondvalue: false }
包含对象的常量是不可变的 对可变数据值的引用。 虽然常量本身无法更改,但所引用项的属性 对象:
const constantObject = { "firstvalue" : true };
constantObject = false
> Uncaught TypeError: invalid assignment to const 'constantObject'
如果您预计变量不会重新赋值,最佳做法是将该变量设为
常量。使用 const
可告知开发团队或未来的维护人员
不要更改该值,以免破坏代码的假设
决定如何使用它,例如,某个变量最终
针对预期数据类型进行评估的。
变量范围
变量的作用域是指脚本中该变量可用的部分。
在变量的作用域之外,不会将其定义为标识符
包含 undefined
值,但好像尚未声明一样。
根据您用于声明变量的关键字以及 在定义变量后,您可以将变量作用域限定为屏蔽语句(屏蔽作用域), 单个函数(函数范围),或整个 JavaScript 应用 (全局范围)。
屏蔽范围
您使用 let
或 const
声明的任何变量的作用域都限定为最接近的变量
包含 block 语句,
也就是说,只能在该块内访问该变量。正在尝试
访问包含块的块级范围的变量时,会导致同样
尝试访问不存在的变量时发生错误:
{
let scopedVariable = true;
console.log( scopedVariable );
}
> true
scopedVariable
> ReferenceError: scopedVariable is not defined
就 JavaScript 而言,块级范围的变量不存在 在包含它的块之外。例如,您可以声明一个常量, 然后在该代码块之外声明另一个常量,该常量使用 相同的标识符:
{
const myConstant = false;
}
const myConstant = true;
scopedConstant;
> true
虽然声明的变量无法扩展到其父块中,但它是 可用于所有后代块:
{
let scopedVariable = true;
{
console.log( scopedVariable );
}
}
> true
可以在后代块中更改声明的变量的值:
{
let scopedVariable = false;
{
scopedVariable = true;
}
console.log( scopedVariable );
}
> true
可通过在后代内使用 let
或 const
来初始化新变量
块中没有任何错误,即使它使用的标识符与变量中的变量相同,
父块:
{
let scopedVariable = false;
{
let scopedVariable = true;
}
console.log( scopedVariable );
}
> false
函数范围
使用 var
声明的变量的作用域限定为最接近的包含函数
(或类中的静态初始化块)。
function myFunction() {
var scopedVariable = true;
return scopedVariable;
}
scopedVariable;
> ReferenceError: scopedVariable is not defined
调用函数后,情况仍然如此。虽然 一个变量是在函数执行时进行初始化的,则该变量仍然 在函数范围之外不可用:
function myFunction() {
var scopedVariable = true;
return scopedVariable;
}
scopedVariable;
> ReferenceError: scopedVariable is not defined
myFunction();
> true
scopedVariable;
> ReferenceError: scopedVariable is not defined
全局范围
全局变量在整个 JavaScript 应用中都可用, 添加到网页上的任何脚本中。
虽然这看起来似乎很不错,但 可能会增加不必要的开销,甚至可能导致 与应用中其他位置具有相同标识符的变量冲突。 这适用于网页呈现过程中涉及的所有 JavaScript 包括第三方库和用户分析等因此, 遵循最佳实践,尽可能避免污染全局范围。
在父函数之外使用 var
或者使用 let
或
在父块外的 const
是全局性的:
var functionGlobal = true; // Global
let blockGlobal = true; // Global
{
console.log( blockGlobal );
console.log( functionGlobal );
}
> true
> true
(function() {
console.log( blockGlobal );
console.log( functionGlobal );
}());
> true
> true
在未明确声明的情况下为变量赋值(也就是说,
绝不使用 var
、let
或 const
来创建)会将变量提升为
全局作用域,即使在函数或块内初始化时也是如此。变量
使用这种模式创建的内容有时称为“隐式全局”。
function myFunction() {
globalVariable = "global";
return globalVariable
}
myFunction()\
> "global"
globalVariable\
> "global"
变量提升
变量和函数声明会提升到其作用域的顶部,
JavaScript 解释器会处理在任何阶段
并有效地将其移到包含所选脚本的第一行
作用域。也就是说,使用
可以在声明变量之前引用 var
,而不会遇到
错误:
hoistedVariable
> undefined
var hoistedVariable;
由于只托管变量声明,而不是初始化,
尚未使用 var
、let
或 const
明确声明的变量
未提升:
unhoistedVariable;
> Uncaught ReferenceError: unhoistedVariable is not defined
unhoistedVariable = true;
如前所述,一个已声明但未初始化的变量
分配的值为 undefined
。该行为适用于提升的变量
声明,但仅限于使用 var
声明的那些。
hoistedVariable
> undefined
var hoistedVariable = 2 + 2;
hoistedVariable\
> 4
这种不直观的行为在很大程度上阻碍了 最早的 JavaScript 版本,并且无法更改,除非出现 破坏现有网站
let
和 const
解决了此行为,方法是在发生以下情况时抛出错误:
变量在创建之前对其进行访问:
{
hoistedVariable;
let hoistedVariable;
}
> Uncaught ReferenceError: can't access lexical declaration 'hoistedVariable' before initialization
此错误与“hoistedVariable is notundefined”不同出错了
。由于 JavaScript
已经提升该变量,但知道该变量将在
给定的范围。不过,与其让该变量在其
值为 undefined
时,解释器会抛出错误。
使用 let
或 const
(或 class
)声明的变量称存在于
“时间死区”(“TDZ”)
在代码中声明变量的位置。
时间死区使得 let
的行为比 var
更直观:
作者。它对于 const
的设计也至关重要。因为常数不能
已更改,一个提升到其作用域顶部且给定隐式值的常量
有 1 个 undefined
无法使用任何有意义的值进行初始化。
检查您的理解情况
标识符可以使用哪些类型的字符开头?
如果要声明某个变量的值, 可以随时更改?