- var 变量总是提升到当前函数作用域的顶端
- let,const 为块级作用域,
变量声明提升
var与let作用域规则不一样
- var: 变量总是提升到当前函数作用域的顶端
- 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 存在暂存死区
- var: 变量提升,会被移动到函数顶端,被初始化为undefined,存在函数堆栈内
- 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
- code01: var 会被提升到函数的顶端, 因此处于同一块级作用域,所以抛异常
SyntaxError
- code02: ++ 修改的是块级作用域内的 x 的值,所以 外面 x 的值不变
函数声明提升
普通提升
js
hoisted(); // "foo"
function hoisted() {
console.log("foo");
}
js
var hoisted;
hoisted = function() {
console.log("foo");
}
hoisted();
相同点:
- var, function 都会被提升
不同点:
- var 提升在 function 之前
- 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
- code01: 变量提升,函数未提升,执行undefind(),所以报错:TypeError
- code02: foo 没有被声明,没有找到foo,所以报错: ReferenceError