【ES6 教程】01—新的ES6语法:JavaScript let 声明块作用域变量

87d04c623ad459356904eba09122b0bd.png

英文教程 | https://www.javascripttutorial.net/

翻译 | 杨小二

ECMAScript 2015 或 ES2015 是对 JavaScript 编程语言的重大更新。这是自 2009 年 ES5 标准化以来对该语言的第一次重大更新。因此,ES2015 通常被称为 ES6。

要学习本 ES6 教程,你应该对 ES5 之前的 JavaScript 有很好的了解。

在本教程中,你将学习如何使用 JavaScriptlet关键字来声明块范围的变量。

JavaScript let 关键字简介

在 ES5 中,当你使用关键字声明变量时,变量var的作用域是全局的或局部的。如果在函数外声明变量,则变量的作用域是全局的。在函数内部声明变量时,变量的作用域是局部的。

ES6 提供了一种使用let关键字声明变量的新方法。该let关键字类似于var关键字,所不同的是这些变量被阻止-范围。例如:

 
 
let variable_name;

在JavaScript中,块是由大括号来表示{},例如,if else,  for,do while,while,try catch等:

 
 
if(condition) {
   // inside a block
}

请参阅以下示例:

 
 
let x = 10;
if (x == 10) {
    let x = 20;
    console.log(x); // 20:  reference x inside the block
}
console.log(x); // 10: reference at the begining of the script

脚本的工作原理:

  • 首先,声明一个变量x并将其值初始化为 10。

  • 其次,x在if块内声明一个同名的新变量,但初始值为 20。

  • 第三,输出块x内和if块后  变量的值。

因为let关键字声明了一个块范围的变量,块x内的变量if是一个新变量,它隐藏了x在脚本顶部声明的变量。因此,控制台x中的值为20。

当 JavaScript 引擎完成执行if块时,块x内的变量if超出范围。因此, 块x后面的变量的if 值为 10。

JavaScript let 和全局对象

当你使用var关键字声明一个全局变量时,你将该变量添加到全局对象的属性列表中。对于 Web 浏览器,全局对象是window. 例如:

 
 
var a = 10;
console.log(window.a); // 10

但是,当你使用let关键字声明变量时,该变量不会作为属性附加到全局对象。例如:

 
 
let b = 20;
console.log(window.b); // undefined

for 循环中的 JavaScript let 和回调函数

请参阅以下示例。

 
 
for (var i = 0; i < 5; i++) {
    setTimeout(function () {
        console.log(i);
    }, 1000);
}

该代码的目的是每秒向控制台输出 0 到 4 之间的数字。但是,它会输出该数字5五次:

 
 
5
5
5
5
5

在这个例子中,变量i是一个全局变量。在循环之后,它的值为 5。当回调函数被传递给setTimeout()函数执行时,它们引用i与值 5相同的变量。

在 ES5 中,你可以通过创建另一个作用域来解决此问题,以便每个回调函数引用一个新变量。并且要创建一个新的作用域,你需要创建一个函数。通常,你可以按如下方式使用IIFE模式:

 
 
for (var i = 0; i < 5; i++) {
    (function (j) {
        setTimeout(function () {
            console.log(j);
        }, 1000);
    })(i);
}

输出:

 
 
0
1
2
3
4

在 ES6 中,let关键字在每次循环迭代中声明一个新变量。因此,你只需将var关键字替换为let关键字即可解决问题:

 
 
for (let i = 0; i < 5; i++) {
    setTimeout(function () {
        console.log(i);
    }, 1000);
}

为了让代码完全 ES6 风格,可以使用如下箭头函数:

 
 
for (let i = 0; i < 5; i++) {
    setTimeout(() => console.log(i), 1000);
}

请注意,你将在后面的教程中了解有关箭头函数的更多信息。

重新申报

该var关键字允许你重新声明变量而不会出现任何问题:

 
 
var counter = 0;
var counter;
console.log(counter); // 0

但是,使用let关键字重新声明变量将导致错误:

 
 
let counter = 0;
let counter;
console.log(counter);

这是错误消息:

 
 
Uncaught SyntaxError: Identifier 'counter' has already been declared

JavaScript let 变量和提升

让我们检查以下示例:

 
 
{
    console.log(counter); // 
    let counter = 10;    
}

此代码导致错误:

 
 
Uncaught ReferenceError: Cannot access 'counter' before initialization

在此示例中,counter在声明变量之前访问该变量会导致ReferenceError, 你可能认为使用let关键字的变量声明不会提升,但会提升。

实际上,JavaScript 引擎会将let关键字声明的变量提升到块的顶部。但是,JavaScript 引擎不会初始化该变量。

因此,当你引用一个未初始化的变量时,你会得到一个ReferenceError。

暂时死亡区(TDZ)

由let关键字声明的变量具有所谓的时间死区 (TDZ)。TDZ 是从块开始到处理变量声明的时间。

以下示例说明时间死区是基于时间的,而不是基于位置的。

 
 
{ // enter new scope, TDZ starts
    let log = function () {
        console.log(message); // messagedeclared later
    };


    // This is the TDZ and accessing log
    // would cause a ReferenceError


    let message= 'Hello'; // TDZ ends
    log(); // called outside TDZ
}

在这个例子中:

首先,大括号开始一个新的块作用域,因此,TDZ 开始。

其次,log()函数表达式访问message变量。但是,该log()功能尚未执行。

第三,声明message变量并将其值初始化为10。从块作用域开始到message变量被访问的时间称为临时死亡区。当 JavaScript 引擎处理声明时,TDZ 结束。

最后,调用log()访问messageTDZ外变量的函数。

请注意,如果你访问由letTDZ 中的关键字声明的变量,你将获得 a ReferenceError,如下例所示。

 
 
{ // TDZ starts
    console.log(typeof myVar); // undefined
    console.log(typeof message); // ReferenceError
    let message; // TDZ ends
}

注意myVarvariable 是一个不存在的变量,因此,它的类型是undefined。

临时死亡区可防止你在声明之前意外引用变量。

概括

  • 使用let关键字声明的变量是块范围的,没有初始化为任何值,也没有附加到全局对象。

  • 使用let关键字重新声明变量将导致错误。

  • 使用let关键字声明的变量的时间死区从块开始,直到评估初始化。

学习更多技能

请点击下方公众号

0a5e418a72ce9e4441b2f4a60261e8a4.gif

132346bfe3c0316efe258bb2809acf21.png

7226658583de69ff95a11b4b1da2931a.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值