var VS let VS const

220 阅读3分钟

1. Scoping rules / 块级作用域

var在全局中生效,而letconst只在{}内生效

var foo = "Foo";
let bar = "Bar";

console.log(foo, bar); // Foo Bar

{
var moo = "Mooo"
let baz = "Bazz";
console.log(moo, baz); // Mooo Bazz
}

console.log(moo); // Mooo
console.log(baz); // ReferenceError

JS中的for循环体比较特殊,每次执行都是一个全新的独立的块作用域

for (var i = 0; i <10; i++) {  
  setTimeout(function() {  // 同步注册回调函数到 异步的 宏任务队列。
    console.log(i);        // 执行此代码时,同步代码for循环已经执行完成
  }, 0);
}
// 输出结果
1010

i虽然在全局作用域声明,但是在for循环体局部作用域中使用的时候,变量会被固定,不受外界干扰。

for (let i = 0; i < 10; i++) { 
  setTimeout(function() {
    console.log(i);    //  i 是循环体内局部作用域,不受外界影响。
  }, 0);
}
// 输出结果:
0  1  2  3  4  5  6  7  8 9

ES6 明确规定,如果区块中存在letconst命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。
总之,在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”temporal dead zone,简称 TDZ

2. Hoisting / 变量提升

使用var时, 变量会在声明前初始化为undefined

console.log(foo); // undefined
var foo = "Foo";
console.log(foo); // Foo

let不会初始化,会报错ReferenceError

console.log(foo); // ReferenceError
let foo = "Foo";
console.log(foo); // Foo

因为变量提升, 当在最外层函数的外部声明var变量时,作用域是全局的。 这意味着在最外层函数的外部用var声明的任何变量都可以在windows中使用。
At the top level, let, unlike var, does not create a property on the global object:

var foo = "Foo";  // globally scoped
let bar = "Bar"; // not allowed to be globally scoped

console.log(window.foo); // Foo
console.log(window.bar); // undefined

3. Redeclaration

In strict mode, var will let you re-declare the same variable in the same scope while let raises a SyntaxError.
let在同一作用域里只能声明一次。

'use strict';
var foo = "foo1";
var foo = "foo2"; // No problem, 'foo1' is replaced with 'foo2'.

let bar = "bar1"; 
let bar = "bar2"; // SyntaxError: Identifier 'bar' has already been declared

4.const 不能被修改并且不能被重新声明

const greeting = 'say Hi';
greeting = 'say Hello instead'; // error: Assignment to constant variable.
const greeting = 'say Hi';
const greeting = 'say Hello instead'; // error: Identifier 'greeting' has already been declared

当用const声明对象时,这种行为却有所不同。 虽然不能更新const对象,但是可以更新该对象的属性。 因此,如果我们声明一个const对象为

const greeting = {
    message: 'say Hi',
    times: 4,
};

同样不能像下面这样做:

const greeting = {
    words: 'Hello',
    number: 'five',
}; // error:  Assignment to constant variable.

但我们可以这样做:

greeting.message = 'say Hello instead';

最后,我们总结一下它们的异同:

  • var声明是全局作用域或函数作用域,而letconst是块作用域。
  • var变量可以在其范围内更新和重新声明; let变量可以被更新但不能重新声明; const变量既不能更新也不能重新声明。
  • 它们都被提升到其作用域的顶端。 但是,虽然使用变量undefined初始化了var变量,但未初始化letconst变量。
  • 尽管可以在不初始化的情况下声明varlet,但是在声明期间必须初始化const。 source:

stackoverflow.com/questions/7…

www.cnblogs.com/fly_dragon/…

chinese.freecodecamp.org/news/javasc…