今天学习了let,在此记录下来。
let命令和var一样,也是定义一个变量,但是let声明的变量只在所在的代码块有效:
以下例子都摘自阮一峰老师的博客:
{
let a = 10;
var b = 1;
}
a // ReferenceError: a is not defined.
b //1
for (let i = 0; i < 10; i++) {
// ...
}
console.log(i);//i is not defined
这里还有一个ES5时候经典的例子:
var a = [];
for (var i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[0]();//10
a[1]();//10
a[2]();//10
a[3]();//10
为什么都输出10呢?因为虽然我们在for里面定义的var i;实际上被提升到了外面,和var a 一个层次,所以当我们去输出i的时候,这时候的i已经被加到10了。
如果我们把var 改为let:
var a = [];
for (let i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[0]();//0
a[1]();//1
a[2]();//2
a[3]();//3
在每次调用a[x]()的时候会进入到a[i] = function () {
console.log(i);
};里面,打印对应的i,其实这里还是有些不懂,不过打了debug跟进去看确实如此,就是这个时候的i是怎么确认是几的,然后看到了阮一峰老师的解释:“变量i
是let
声明的,当前的i
只在本轮循环有效,所以每一次循环的i
其实都是一个新的变量,所以最后输出的是6
。你可能会问,如果每一轮循环的变量i
都是重新声明的,那它怎么知道上一轮循环的值,从而计算出本轮循环的值?这是因为 JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i
时,就在上一轮循环的基础上进行计算。”
大概懂了一点吧。
顺便再记录一下:
设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。
for (let i = 0; i < 3; i++) {
let i = 'abc';
console.log(i);
}
上面代码正确运行,输出了 3 次abc。这表明函数内部的变量i与循环变量i不在同一个作用域,有各自单独的作用域。
但是如果这样:
for (let i = 0; i < 3; i++) {
console.log(i);
} 也能正确打出0, 1,2有点不太懂。这个i不是能进去到循环体里面么,为啥在循环体里面还可以let i呢?
暂时记录下来。
2018-6-21更新
在jsTips看到一句话,有些用处:
通过 var 定义的变量,它的作用域是在 function 或任何外部已经被声明的 function,是全域的 。
透過 let 定义的变量,它的作用域是在一個块(block)。
2018-9-4更新
在阮一峰老师的 ES6 let上面看到了关于“暂时性死区”的描述:
暂时性死区:temporal dead zone,简称 TDZ,在代码块内,使用let
命令声明变量之前,该变量都是不可用的。
一般情况下
t = 'abc';
console.log(t); // "abc"
有了let以后
t = 'abc'; // ReferenceError
console.log(t); // ReferenceError
let t; // TDZ结束
2018-9-6更新
摘自淘宝前端团队
const 的定义是不可重新赋值的值,与不可变的值(immutable value)不同;const 定义的 Object,在定义之后仍可以修改其属性。