1. 基本用法
ES6 新增了
let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。
{
let a=5;
console.log(a); // 5
}
console.log(a); //error:a is not defined
let命令定义的变量a只在块级作用域内生效
-
用来做
for循环的计数器就很合适for(let i=0;i<10;i++){ ... } console.log(i); //error: i is not defined
上述代码中,i之在for循环体内生效,在循坏体外则是未定义
-
另外,
for循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。(有别于函数定义时的情况)for (let i = 0; i < 3; i++) { let i = 'a'; console.log(i); } // a // a // a
上面代码正确运行,输出了 3 次abc。这表明循环体内部的变量i与循环变量i不在同一个作用域,有各自单独的作用域。
2.不存在变量提升
-
var命令会发生“变量提升”现象,即变量可以在声明之前使用,值为undefined。而
let命令则改变了这一语法现象,它所声明的变量一定要在声明后使用,否则报错。// var 的情况 console.log(a); // undefined var a = 2; // let 的情况 console.log(b); // error :b is not defined let b = 2;上面代码中,变量
a使用var命令声明,会发生变量提升,即将此段声明语句在代码开始运行前就存在了,所以输出结果是undefined(赋值语句还没进行);而变量b是用let命令声明,不会发生变量提前,所以会抛出一个错误b is not defined
3.暂时性死区
- 只要块级作用域中存在let命令,它所声明的变量将会被绑定,不受外部作用域的影响。
//暂时性死区
var dead="out_dead";
var alive="out_alive"
{
console.log(dead); //errer:dead is not defined
console.log(alive); // out_alive
let dead="in_dead";
}
上述代码中,存在全局变量dead和alive,但由于变量dead在代码块内用let命令重新声明,导致变量dead绑定在了块级作用域中,又由于let命令没有变量提升,所以控制台抛出一个错误,相较之下变量alive则可以正常输出。
死区范围演示
if(true){
//TDZ开始
a="dead";
console.log(a); //error: a is not defined
let a;
//TDZ结束
console.log(a); //undefined
a=3;
console.log(a); // 3 }
上述代码中,在let语句声明变量a之前,都属于变量a的“暂时性死区
4.不允许重复声明
-
let不允许在相同作用域内重复声明同一个变量
function func(arg) { let arg; } func() // error
function func(arg) { { let arg; } } func() // 不报错
上述代码说明,func(arg)的作用域和函数内部的作用域是相同作用域。
// 报错
function func() {
let a = 10;
var a = 1;
}
// 报错
function func() {
let a = 10;
let a = 1;
}
5.let变量与顶层对象
顶层对象,在浏览器环境指的是
window对象,在 Node 指的是global对象。ES5 之中,顶层对象的属性与全局变量是等价的。
var a=3;
console.log(window.a); // 3
window.a=5;
console.log(a); // 5
上述代码表示,顶层对象的属性赋值,与全局变量的属性赋值是一回事;
-
可能会覆盖window对象原有的属性,造成不必要的程序错误
var ScreenX="test";
console.log(window.ScreenX); // 输出结果为 test
-
解决方案
let ScreenX="test";
console.log(window.ScreenX); //浏览器窗口距离屏幕左边的距离
6.只能出现在顶层作用域
// 第一种写法,报错
if (true) let x = 1;
// 第二种写法,不报错
if (true) {
let x = 1;
}
上面代码中,第一种写法没有大括号,所以不存在块级作用域,而let只能出现在当前作用域的顶层,所以报错。第二种写法有大括号,所以块级作用域成立。
参考文献:阮一峰 《ES6入门教程》 https://es6.ruanyifeng.com/
长路漫漫,共同作伴