var

描述

变量声明,无论发生在何处,都在执行任何代码之前进行处理。用 var 声明的变量的作用域是它当前的执行上下文,它可以是嵌套的函数,或者对于声明在任何函数外的变量来说是全局。如果你重新声明一个 JavaScript 变量,它将不会丢失其值。
当赋值给未声明的变量, 则执行赋值后, 该变量会被隐式地创建为全局变量(它将成为全局对象的属性)。

变量提升

由于变量声明(以及其他声明)总是在任意代码执行之前处理的,所以在代码中的任意位置声明变量总是等效于在代码开头声明。这意味着变量可以在声明之前使用,这个行为叫做“hoisting”。“hoisting”就像是把所有的变量声明移动到函数或者全局代码的开头位置。

let

描述

let允许你声明一个作用域被限制在 级中的变量、语句或者表达式。与 var 关键字不同的是, var声明的变量只能是全局或者整个函数块的。 varlet 的不同之处在于后者是在编译时才初始化。

作用域规则

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)。该变量处在一个自块顶部到初始化处理的“暂存死区”中。

  1. function do_something() {
  2. console.log(bar); // undefined
  3. console.log(foo); // ReferenceError
  4. var bar = 1;
  5. let foo = 2;
  6. }

暂存死区和静态作用域/词法作用域的相关例子

  1. function test(){
  2. var foo = 33;
  3. if (foo) {
  4. let foo = (foo + 55); // ReferenceError
  5. }
  6. }
  7. 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声明创建一个值的只读引用。但这并不意味着它所持有的值是不可变的,只是变量标识符不能重新分配。例如,在引用内容是对象的情况下,这意味着可以改变对象的内容。

常量要求一个初始值

  1. // 报错
  2. // Uncaught SyntaxError: Missing initializer in const declaration
  3. const FOO;

常量可以定义成对象和数组

  1. const MY_OBJECT = {'key': 'value'};
  2. // 重写对象和上面一样会失败
  3. // Uncaught TypeError: Assignment to constant variable.
  4. MY_OBJECT = {'OTHER_KEY': 'value'};
  5. // 对象属性并不在保护的范围内
  6. // 下面这个声明会成功执行
  7. MY_OBJECT.key = 'otherValue'; // Use Object.freeze() to make object immutable
  8. // 也可以用来定义数组
  9. const MY_ARRAY = [];
  10. // 可以向数组填充数据
  11. MY_ARRAY.push('A'); // ["A"]
  12. // 但是,将一个新数组赋给变量会引发错误
  13. // Uncaught TypeError: Assignment to constant variable.
  14. MY_ARRAY = ['B'];