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