var
描述
变量声明,无论发生在何处,都在执行任何代码之前进行处理。用 var
声明的变量的作用域是它当前的执行上下文,它可以是嵌套的函数,或者对于声明在任何函数外的变量来说是全局。如果你重新声明一个 JavaScript 变量,它将不会丢失其值。
当赋值给未声明的变量, 则执行赋值后, 该变量会被隐式地创建为全局变量(它将成为全局对象的属性)。
变量提升
由于变量声明(以及其他声明)总是在任意代码执行之前处理的,所以在代码中的任意位置声明变量总是等效于在代码开头声明。这意味着变量可以在声明之前使用,这个行为叫做“hoisting”。“hoisting”就像是把所有的变量声明移动到函数或者全局代码的开头位置。
let
描述
let
允许你声明一个作用域被限制在 块
级中的变量、语句或者表达式。与 var
关键字不同的是, var
声明的变量只能是全局或者整个函数块的。 var
和 let
的不同之处在于后者是在编译时才初始化。
作用域规则
let 语句声明一个块级作用域的本地变量,并且可选的将其初始化为一个值。**let**
声明的变量只在其声明的块或子块中可用,这一点,与**var**
相似。二者之间最主要的区别在于**var**
声明的变量的作用域是整个封闭函数。
重复声明
在同一个函数或块作用域中重复声明同一个变量会引起SyntaxError
。
暂存死区
与通过 [var](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var#var_hoisting)
声明的有初始化值 undefined
的变量不同,通过 let
声明的变量直到它们的定义被执行时才初始化。在变量初始化前访问该变量会导致 [ReferenceError](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/ReferenceError)
。该变量处在一个自块顶部到初始化处理的“暂存死区”中。
function do_something() {
console.log(bar); // undefined
console.log(foo); // ReferenceError
var bar = 1;
let foo = 2;
}
暂存死区和静态作用域/词法作用域的相关例子
function test(){
var foo = 33;
if (foo) {
let foo = (foo + 55); // ReferenceError
}
}
test();
由于词法作用域,表达式(foo + 55)
内的标识符foo
被认为是if块的foo变量,而不是值为33的块外面的变量foo。
在同一行,这个if块中的foo
已经在词法环境中被创建了,但是还没有到达(或者终止)它的初始化(这是语句本身的一部分)。
这个if块里的foo
还依旧在暂存死区里。
const
描述
此声明创建一个常量,其作用域可以是全局或本地声明的块。 与[var](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/var)
变量不同,全局常量不会变为 window 对象的属性。需要一个常数的初始化器;也就是说,您必须在声明的同一语句中指定它的值(这是有道理的,因为以后不能更改)。const
声明创建一个值的只读引用。但这并不意味着它所持有的值是不可变的,只是变量标识符不能重新分配。例如,在引用内容是对象的情况下,这意味着可以改变对象的内容。
常量要求一个初始值
// 报错
// Uncaught SyntaxError: Missing initializer in const declaration
const FOO;
常量可以定义成对象和数组
const MY_OBJECT = {'key': 'value'};
// 重写对象和上面一样会失败
// Uncaught TypeError: Assignment to constant variable.
MY_OBJECT = {'OTHER_KEY': 'value'};
// 对象属性并不在保护的范围内
// 下面这个声明会成功执行
MY_OBJECT.key = 'otherValue'; // Use Object.freeze() to make object immutable
// 也可以用来定义数组
const MY_ARRAY = [];
// 可以向数组填充数据
MY_ARRAY.push('A'); // ["A"]
// 但是,将一个新数组赋给变量会引发错误
// Uncaught TypeError: Assignment to constant variable.
MY_ARRAY = ['B'];