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); // undefinedconsole.log(foo); // ReferenceErrorvar 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 declarationconst 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'];
