Skip to content
  1. var 变量总是提升到当前函数作用域的顶端
  2. let,const 为块级作用域,

变量声明提升

var与let作用域规则不一样

  1. var: 变量总是提升到当前函数作用域的顶端
  2. let: 当前块的作用域
js
function varTest() {
    var x = 1;
    {
        var x = 2; // 同样的变量!
        console.log(x); // 2
    }
    console.log(x); // 2
}

function letTest() {
    let x = 1;
    {
        let x = 2; // 不同的变量
        console.log(x); // 2
    }
    console.log(x); // 1
}

let 可以用来创建类的私有属性

js
var Thing;

{
    let privateScope = new WeakMap();
    let counter = 0;

    Thing = function () {
        this.someProperty = 'foo';

        privateScope.set(this, {
            hidden: ++counter
        });
    };

    Thing.prototype.showPublic = function () {
        return this.someProperty;
    };
}

let 不能重复声明

js
if (x) {
    let foo;
    let foo; // SyntaxError thrown.
}

if (x) {
    var foo;
    var foo;
}

let x = 1;
switch (x) {
    case 0:
        let foo;
        break;

    case 1:
        let foo; // SyntaxError for redeclaration.
        break;
}

let, const 存在暂存死区

  1. var: 变量提升,会被移动到函数顶端,被初始化为undefined,存在函数堆栈内
  2. let: 不会变量提升,直至显示赋值才会被加入函数执行堆栈内,在块级作用域开始时,会被放到暂存死区, 无法被引用
js
// prints out 'undefined'
console.log(typeof undeclaredVariable);

// results in a 'ReferenceError'
console.log(typeof i);
let i = 10;

习题解释

js
// code01
let x = 1;
{
    var x = 2; // SyntaxError for re-declaration
}
js
// code02
var x = 1;
{
    let x = 2;
    x++;
}
console.log(x); // 1
  1. code01: var 会被提升到函数的顶端, 因此处于同一块级作用域,所以抛异常SyntaxError
  2. code02: ++ 修改的是块级作用域内的 x 的值,所以 外面 x 的值不变

函数声明提升

普通提升

js
hoisted(); // "foo"

function hoisted() {
    console.log('foo');
}
js
var hoisted;

hoisted = function () {
    console.log('foo');
};
hoisted();

相同点:

  1. var, function 都会被提升

不同点:

  1. var 提升在 function 之前
  2. var 为函数级提升,function 为块级提升

有条件提升

js
// code01
foo(); // Uncaught TypeError: foo is not a function
{
    function foo() {
        return 1;
    }
}

// 在Chrome里:
// 'foo' 变量名被提升,但是 typeof foo 为 undefined
//
// 在Firefox里:
// 'foo' 变量名被提升. 但是 typeof foo 为 undefined
//
// 在Edge里:
// 'foo' 变量名未被提升. 而且 typeof foo 为 undefined
//
// 在Safari里:
// 'foo' 变量名被提升. 而且 typeof foo 为 function
js
// code02
foo(); //Uncaught ReferenceError: foo is not defined
  1. code01: 变量提升,函数未提升,执行undefind(),所以报错:TypeError
  2. code02: foo 没有被声明,没有找到foo,所以报错: ReferenceError