ES6 新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。
一. 概述 es6新增let
关键字作用? 答:用于声明变量,声明的变量只在let命令所在的代码块内有效。
let
有什么特点与var
相比不同点? 答:① let
不存在变量提升,var
存在变量提升;② let定义变量需要先定义后使用,否则抛出异常;③ let
不允许在相同作用域内,重复声明同一个变量。而var可以
二. let 命令
1.作用
let
命令是ES6 新增命令。用于声明变量,声明的变量只在let
命令所在的代码块内有效。
① 特点-不存在变量提升
let
不存在变量提升,var
存在变量提升
//var 定义的b发生了变量提升 let定义的a抛出异常
{
let a = 10;
var b = 1;
}
a // ReferenceError: a is not defined.
b // 1
② 特点-let定义变量需要先定义后使用
let定义变量需要先定义后使用,否则抛出异常
// var 的情况
console.log(foo); // 输出undefined
var foo = 2;
// let 的情况
console.log(bar); // 报错ReferenceError
let bar = 2;
③特点-不允许重复声明
let
不允许在相同作用域内,重复声明同一个变量。
// 报错
function func() {
let a = 10;
var a = 1;
}
// 报错
function func() {
let a = 10;
let a = 1;
}
因此,也不能在函数内部重新声明参数。
function func(arg) {
let arg;
}
func() // 报错
function func(arg) {
{
let arg;
}
}
func() // 不报错
④特点-暂时性死区
在块级作用域中,如果使用let
命令声明某变量,则此块级作用域中此变量必须先声明后使用。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)
ES6 明确规定,如果区块中存在let
和const
命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。
//块级中tmp指向了let定义的tmp
var tmp = 123;
if (true) {
tmp = 'abc'; // ReferenceError
let tmp;
}
if (true) {
// TDZ开始
tmp = 'abc'; // ReferenceError
console.log(tmp); // ReferenceError
let tmp; // TDZ结束
console.log(tmp); // undefined
tmp = 123;
console.log(tmp); // 123
}
// 不报错
var x = x;
// 报错
let x = x;
// ReferenceError: x is not defined
对typeof
的影响,若不在暂时性死区内如果一个变量根本没有被声明,使用typeof
会打印"undefined";而在暂时性死区内则会报错
{
typeof x; // ReferenceError
let x;
}
//不在死区内
typeof undeclared_variable // "undefined"
⑤特点-在for循环中适合使用let
for
循环的,适合使用let
命令。
//i只在for循环体内有效
for (let i = 0; i < 10; i++) {
// ...
}
console.log(i);
// ReferenceError: i is not defined
for
循环中使用var和let对比
//for循环将函数赋值在数组中,并打印i值,当时因为var i是全局变量,所以a数组中所有函数都打印10
var a = [];
for (var i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 10
//let i变量在每次循环都生成一个新变量,不会出现打印相同数据的问题
var a = [];
for (let i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 6
for
循环,循环变量和循环体的作用域是各自独立的,设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。
//函数内部的变量i与循环变量i不在同一个作用域,有各自单独的作用域
for (let i = 0; i < 3; i++) {
let i = 'abc';
console.log(i);
}
// abc
// abc
// abc