1. let声明的变量只在它所在的代码块有效
{ let a = 10; 3 var b = 1; 4 } 5 a // ReferenceError: a is not defined. 6 b // 1
for(var i=0; i<10; i++){ a[i]=function(){ console.log(i); } } a[6](); //10 比较 var a=[]; for(let i=0;i<10;i++){ a[i]=function(){ console.log(i); } } a[6]() let 生成6个作用域 每个作用域有各自的i 和全局作用域,,,而var 声明的 只有全局作用域和各自的函数作用域
2.var“变量提升”现象是变量在申明前使用,会返回underfined。let不像那样会发生“变量提升”现象。所以变量一定要在声明后使用,否则报错。
3.在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称TDZ)。
4 .暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。
function test(x = y, y = 2) {
return [x, y];
}
test(); // 报错
function test(x = 2, y = x) {
return [x, y];
}
test(); // [2, 2]
ES6为了改变这一点,一方面规定,为了保持兼容性,var命令和function命令声明的全局变量,依旧是全局对象的属性;另一方面规定,let命令、const命令、class命令声明的全局变量,不属于全局对象的属性。也就是说,从ES6开始,全局变量将逐步与全局对象的属性脱钩
var a = 1; // 如果在Node的REPL环境,可以写成global.a // 或者采用通用方法,写成this.a window.a // 1 let b = 1; window.b // undefined
下面是一个将对象彻底冻结的函数
var constantize = (obj) => {
Object.freeze(obj);
Object.keys(obj).forEach( (key, value) => {
if ( typeof obj[key] === 'object' ) {
constantize( obj[key] );
}
});
};
const命令只是保证变量名指向的地址不变,并不保证该地址的数据不变,所以将一个对象声明为常量必须非常小心。
const foo = {};
foo.prop = 123;
foo.prop
// 123
foo = {}; // TypeError: "foo" is read-only
考虑到环境导致的行为差异太大,应该避免在块级作用域内声明函数。如果确实需要,也应该写成函数表达式,而不是函数声明语句。
// 函数声明语句
{
let a = 'secret';
function f() {
return a;
}
}
// 函数表达式
{
let a = 'secret';
let f = function () {
return a;
};
}
ES5只有两种声明变量的方法:var命令和function命令。ES6除了添加let和const命令,后面章节还会提到,另外两种声明变量的方法:import命令和class命令。所以,ES6一共有6种声明变量的方法。
补充整理:
对于let 和 const 最大的好处就是避免了可能的运行时错误, 不过也有直观的好处:
- 用块(Blocks)替换立即执行函数(IIFEs)
- 定义循环变量不会外泄
- 循环定义函数可以不用闭包了
- 可以放心的在 if 等条件中定义函数
浙公网安备 33010602011771号