TypeScript入门教程 之 Let 关键字
let
var
JavaScript中的变量是函数范围的。这不同于许多其他语言(C#/ Java等),其中变量是块作用域的。如果将块作用域的思维方式带入JavaScript,您将期望打印以下内容123
,而将打印456
:
var foo = 123; if (true) { var foo = 456; } console.log(foo); // 456
这是因为{
不会创建新的变量范围。该变量foo
在if 块内部与在if 块外部相同。这是JavaScript编程中常见的错误来源。这就是为什么TypeScript(和ES6)引入let
关键字以允许您使用真正的块范围定义变量的原因。就是说,如果您使用let
而不是var
将真正的唯一元素与可能在范围之外定义的元素断开连接。用以下示例演示了相同的示例let
:
let foo = 123; if (true) { let foo = 456; } console.log(foo); // 123
let
使您免于错误的另一个地方是循环。
var index = 0; var array = [1, 2, 3]; for (let index = 0; index < array.length; index++) { console.log(array[index]); } console.log(index); // 0
let
出于诚意,我们发现最好在可能的情况下使用它,因为这会给新的和现有的多语言开发人员带来更少的惊喜。
功能创造了新的范围
自从我们提到它以来,我们想证明函数在JavaScript中创建了一个新的变量范围。考虑以下:
var foo = 123; function test() { var foo = 456; } test(); console.log(foo); // 123
这就像您期望的那样。没有这个,用JavaScript编写代码将非常困难。
生成JS
let
如果周围范围内已经存在类似的名称,则TypeScript生成的JS可以简单地重命名变量。例如产生以下作为是用一个简单的替代的let
具有var
:
if (true) { let foo = 123; } // becomes // if (true) { var foo = 123; }
但是,如果周围范围已经使用了变量名,那么将生成一个新的变量名,如下所示(注意foo_1
):
var foo = '123'; if (true) { let foo = 123; } // becomes // var foo = '123'; if (true) { var foo_1 = 123; // Renamed }
switch
您可以包装您的case
主体{}
以在不同的case
语句中可靠地重用变量名,如下所示:
switch (name) { case 'x': { let x = 5; // ... break; } case 'y': { let x = 10; // ... break; } }
let in closures
JavaScript开发人员常见的编程面试问题是这个简单文件的日志是什么:
var funcs = []; // create a bunch of functions for (var i = 0; i < 3; i++) { funcs.push(function() { console.log(i); }) } // call them for (var j = 0; j < 3; j++) { funcs[j](); }
人们会期望如此0,1,2
。出乎意料的是,这将同时3
适用于所有三个功能。原因是这三个函数都使用了i
外部作用域中的变量,并且在我们执行它们(在第二个循环中)时,其值i
将为3
(这是第一个循环的终止条件)。
一种解决方法是在特定于该循环迭代的每个循环中创建一个新变量。如前所述,我们可以通过创建一个新函数并立即执行它(即,来自classes的IIFE模式(function() { /* body */ })();
)来创建一个新的变量范围,如下所示:
var funcs = []; // create a bunch of functions for (var i = 0; i < 3; i++) { (function() { var local = i; funcs.push(function() { console.log(local); }) })(); } // call them for (var j = 0; j < 3; j++) { funcs[j](); }
在这里,这些函数关闭(因此称为a closure
)局部变量(方便命名local
),并使用该变量代替循环变量i
。
请注意,闭包会影响性能(它们需要存储周围的状态)。
let
循环中的ES6 关键字与上一个示例具有相同的行为:
var funcs = []; // create a bunch of functions for (let i = 0; i < 3; i++) { // Note the use of let funcs.push(function() { console.log(i); }) } // call them for (var j = 0; j < 3; j++) { funcs[j](); }
使用a let
代替var
创建i
每个循环迭代唯一的变量。
摘要
let
对于绝大多数代码而言,这非常有用。它可以大大提高代码的可读性,并减少编程错误的机会。
翻译来源:https://gitee.com/yunwisdoms/typescript-book/blob/master/docs/let.md