块级作用域
ES5 只有全局作用域和函数作用域(例如,我们必须将代码包在函数内来限制作用域),这导致很多问题:
1、内层变量覆盖外层变量。2、变量泄露,成为全局变量。3、不再需要立即执行的函数表达式。4、循环体中的闭包不再有问题。
var
用 var 定义的全部变量,有时候会污染整个 js 的作用域。1
2
3
4{
var a = 1;
}
console.log(a); // 因为 var 是全局声明的,所以,即使是在区块里声明,但仍然在全局起作用。
let
let使js有块作用域,且变量不提升
1 | { |
经典案例
1 | var a = [] |
解决方案
给函数体里唯一的变量,这样就不会受外界的影响了1
2
3
4
5
6
7
8var a = []
for(let i = 0; i < 6; i++) {
a[i] = function () {
console.log(i)
}
}
a[4]() // 4
a[5]() // 5
for循环里有2个作用域
设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域1
2
3
4
5
6
7for (let i = 0; i < 3; i++) {
let i = 'abc';
console.log(i);
}
// abc
// abc
// abc
暂时性死区
Es6规定:在块作用域内存在let和const时,凡是在声明前使用这些变量,就会报错1
2
3
4
5
6
7
8
9var tmp = 123;
if (true) {
tmp = 'abc'; // ReferenceError
typeof tmp
let tmp;
console.log(tmp) // 'undefined'
typeof tmp // 'undefined'
}
const
const定义的时候就必须赋值,且只保证变量的内存地址不变,所以只要变量的内存地址不变,还是可以改变变量的属性。将对象进行冻结1
2
3
4
5
6
7
8
9
10
11const foo = Object.freeze({});
foo.prop = 123; // 报错
var constantize = (obj) => {
Object.freeze(obj);
Object.keys(obj).forEach( (key, i) => {
if ( typeof obj[key] === 'object' ) {
constantize( obj[key] );
}
});
};
es6一共有几种声明变量
全局变量:window,指的是浏览器窗口对象
顶级变量:没有实质意义,也是window1
2var, function // 定义了会变成顶级变量和全局变量, window.a // 正确
let, const, import, class // 不会变成顶级变量和全局变量 window.a // 报错