1.let命令
es6新增了let命令,用来声明变量,变量只在let所在的代码块内有效,很适合在for中使用,看例子
var a = [];
for (var i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 10
发现输出的跟预期不一致,是因为i是var声明的,属于全局变量,全局范围内只有一个变量i,每次循环i都会改变,所以运行到最后执行i++,所以输出10。用let就可以避免这种问题
var a = [];
for (let i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 6
for循环需要注意的是,设置循环变量的是一个父作用域,而循环体内部是独立的子作用域。
1.1 不存在变量提升
关于变量提升,可以参考www.lagou.com/lgeduarticl…
周知,var命令会变量提升,可以再声明之前使用,值为undefined。let纠正了这种语法,它所声明的变量一定要在声明后使用,否则报错。
1.2 暂时性死区(TDZ)
如果区块中存在let,const命令,这个区块就对这些命令声明的变量封闭,凡是在声明之前使用,都会报错。
var tmp = 123;
if (true) {
tmp = 'abc'; // ReferenceError
let tmp;
console.log(tmp); // undefined
tmp = 123;
console.log(tmp); // 123
}
1.3 不允许重复声明变量
2 块级作用域
es5只有全局作用域和函数作用域,没有块级作用域,会带来一些问题,
var tmp = new Date();
function f() {
console.log(tmp);
var tmp = 'hello world';
}
f(); // undefined
上述,内层变量可能会覆盖外层变量。tmp原本是date对象,执行f()时,检测console的tmp在后又声明,所以tmp为undefined。
var s = 'hello';
for (var i = 0; i < s.length; i++) {
console.log(s[i]);
}
console.log(i); // 5
上述,用来计数的变量,泄露为全局变量。 ES6的块级作用域 let为js新增了块级作用域,
function f1() {
let n = 5;
if (true) {
let n = 10;
}
console.log(n); // 5
}
外层代码块不受内层代码块的影响。
ES6 引入了块级作用域,明确允许在块级作用域之中声明函数。ES6 规定,块级作用域之中,函数声明语句的行为类似于let,在块级作用域之外不可引用。
疑问:let只能出现在当前作用域的顶层?严格模式下,函数只能声明在当前作用域的顶层?
3 const命令
const声明一个只读常量,一旦声明就不可以更改。const一旦声明变量,就必须立即初始化,不能留到以后赋值。作用域只在所在的块级作用域中有效 本质上,const保证的是变量指向的内存地址所保存的数据不可变动,对于简单数据类型,值就保存在变量指向的内存地址,但对于复合型数据类型,变量指向的内存地址,保存一个指向实际数据的指针,const只能保证指针是固定,不能保证他指向的数据结构是否可变。