vue|JavaScript let语法
let 语句声明一个块级作用域的本地变量,并且可选的将其初始化为一个值。
语法
<span style="color:#333333">let var1 [= value1] [, var2 [= value2]] [, ..., varN [= valueN]];</span>
参数
var1
, var2
, …, varN
变量名。可以是任意合法的标识符。
value1
, value2
, …, valueN
变量的初始值。可以是任意合法的表达式。
描述
let允许你声明一个作用域被限制在块级中的变量、语句或者表达式。与var关键字不同的是,var声明的变量只能是全局或者整个函数块的。
点这里可以明白我们为什么选取“let”这个名字。
作用域规则
let声明的变量只在其声明的块或子块中可用,这一点,与var相似。二者之间最主要的区别在于var声明的变量的作用域是整个封闭函数。
<span style="color:#333333"><code>function varTest() {
var x = 1;
if (true) {
var x = 2; // 同样的变量!
console.log(x); // 2
}
console.log(x); // 2
}
function letTest() {
let x = 1;
if (true) {
let x = 2; // 不同的变量
console.log(x); // 2
}
console.log(x); // 1
}</code></span>
简化内部函数代码
当用到内部函数的时候,let会让你的代码更加简单。
<span style="color:#333333"><code class="language-js"><span style="color:#0077aa">var</span> list <span style="color:#a67f59">=</span> document<span style="color:#999999">.</span><span style="color:#dd4a68">getElementById</span><span style="color:#999999">(</span><span style="color:#669900">"list"</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
<span style="color:#0077aa">for</span> <span style="color:#999999">(</span><span style="color:#0077aa">let</span> i <span style="color:#a67f59">=</span> <span style="color:#990055">1</span><span style="color:#999999">;</span> i <span style="color:#a67f59"><=</span> <span style="color:#990055">5</span><span style="color:#999999">;</span> i<span style="color:#a67f59">++</span><span style="color:#999999">)</span> <span style="color:#999999">{</span>
<span style="color:#0077aa">var</span> item <span style="color:#a67f59">=</span> document<span style="color:#999999">.</span><span style="color:#dd4a68">createElement</span><span style="color:#999999">(</span><span style="color:#669900">"LI"</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
item<span style="color:#999999">.</span><span style="color:#dd4a68">appendChild</span><span style="color:#999999">(</span>document<span style="color:#999999">.</span><span style="color:#dd4a68">createTextNode</span><span style="color:#999999">(</span><span style="color:#669900">"Item "</span> <span style="color:#a67f59">+</span> i<span style="color:#999999">)</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
<span style="color:#0077aa">let</span> j <span style="color:#a67f59">=</span> i<span style="color:#999999">;</span>
item<span style="color:#999999">.</span>onclick <span style="color:#a67f59">=</span> <span style="color:#0077aa">function</span> <span style="color:#999999">(</span>ev<span style="color:#999999">)</span> <span style="color:#999999">{</span>
console<span style="color:#999999">.</span><span style="color:#dd4a68">log</span><span style="color:#999999">(</span><span style="color:#669900">"Item "</span> <span style="color:#a67f59">+</span> j <span style="color:#a67f59">+</span> <span style="color:#669900">" is clicked."</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
<span style="color:#999999">}</span><span style="color:#999999">;</span>
list<span style="color:#999999">.</span><span style="color:#dd4a68">appendChild</span><span style="color:#999999">(</span>item<span style="color:#999999">)</span><span style="color:#999999">;</span>
<span style="color:#999999">}</span></code></span>
上面这段代码的意图是创建5个li,点击不同的li能够打印出当前li的序号。如果不用let,而改用var的话,将总是打印出 Item 5 is Clicked,因为 j 是函数级变量,5个内部函数都指向了同一个 j ,而 j 最后一次赋值是5。用了let后,j 变成块级域(也就是花括号中的块,每进入一次花括号就生成了一个块级域),所以 5 个内部函数指向了不同的 j 。
在程序或者函数的顶层,let并不会像var一样在全局对象上创造一个属性,比如
<span style="color:#333333"><code class="language-js"><span style="color:#0077aa">var</span> x <span style="color:#a67f59">=</span> <span style="color:#669900">'global'</span><span style="color:#999999">;</span>
<span style="color:#0077aa">let</span> y <span style="color:#a67f59">=</span> <span style="color:#669900">'global'</span><span style="color:#999999">;</span>
console<span style="color:#999999">.</span><span style="color:#dd4a68">log</span><span style="color:#999999">(</span><span style="color:#0077aa">this</span><span style="color:#999999">.</span>x<span style="color:#999999">)</span><span style="color:#999999">;</span> <span style="color:#708090">// "global"</span>
console<span style="color:#999999">.</span><span style="color:#dd4a68">log</span><span style="color:#999999">(</span><span style="color:#0077aa">this</span><span style="color:#999999">.</span>y<span style="color:#999999">)</span><span style="color:#999999">;</span> <span style="color:#708090">// undefined</span></code></span>
模仿私有接口
在处理构造函数的时候,可以通过let声明而不是闭包来创建私有接口。
var SomeConstructor;
{
let privateScope = {};
SomeConstructor = function SomeConstructor () {
this.someProperty = "foo";
privateScope.hiddenProperty = "bar";
}
SomeConstructor.prototype.showPublic = function () {
console.log(this.someProperty); // foo
}
SomeConstructor.prototype.showPrivate = function () {
console.log(privateScope.hiddenProperty); // bar
}
}
var myInstance = new SomeConstructor();
myInstance.showPublic();
myInstance.showPrivate();
console.log(privateScope.hiddenProperty); // error
let 的暂存死区与错误
在同一个函数或同一个作用域中用let重复定义一个变量将引起 TypeError
.
<span style="color:#333333"><code class="language-js"><span style="color:#0077aa">if</span> <span style="color:#999999">(</span>x<span style="color:#999999">)</span> <span style="color:#999999">{</span>
<span style="color:#0077aa">let</span> foo<span style="color:#999999">;</span>
<span style="color:#0077aa">let</span> foo<span style="color:#999999">;</span> <span style="color:#708090">// TypeError thrown.</span>
<span style="color:#999999">}</span></code></span>
在 ECMAScript 2015 中,let 绑定不受变量提升的约束,这意味着 let 声明不会被提升到当前执行上下文的顶部。在块中的变量初始化之前,引用它将会导致 ReferenceError(而使用 var 声明变量则恰恰相反,该变量的值是 undefined )。这个变量处于从块开始到 let 初始化处理的”暂存死区“之中。
<span style="color:#333333"><code class="language-js"><span style="color:#0077aa">function</span> <span style="color:#dd4a68">do_something</span><span style="color:#999999">(</span><span style="color:#999999">)</span> <span style="color:#999999">{</span>
console<span style="color:#999999">.</span><span style="color:#dd4a68">log</span><span style="color:#999999">(</span>bar<span style="color:#999999">)</span><span style="color:#999999">;</span> <span style="color:#708090">// undefined</span>
console<span style="color:#999999">.</span><span style="color:#dd4a68">log</span><span style="color:#999999">(</span>foo<span style="color:#999999">)</span><span style="color:#999999">;</span> <span style="color:#708090">// ReferenceError: foo is not defined</span>
<span style="color:#0077aa">var</span> bar <span style="color:#a67f59">=</span> <span style="color:#990055">1</span><span style="color:#999999">;</span>
<span style="color:#0077aa">let</span> foo <span style="color:#a67f59">=</span> <span style="color:#990055">2</span><span style="color:#999999">;</span>
<span style="color:#999999">}</span></code></span>
在 switch
声明中你可能会遇到这样的错误,因为一个switch只有一个作用块.
<span style="color:#333333"><code class="language-js"><span style="color:#0077aa">switch</span> <span style="color:#999999">(</span>x<span style="color:#999999">)</span> <span style="color:#999999">{</span>
<span style="color:#0077aa">case</span> <span style="color:#990055">0</span><span style="color:#999999">:</span>
<span style="color:#0077aa">let</span> foo<span style="color:#999999">;</span>
<span style="color:#0077aa">break</span><span style="color:#999999">;</span>
<span style="color:#0077aa">case</span> <span style="color:#990055">1</span><span style="color:#999999">:</span>
<span style="color:#0077aa">let</span> foo<span style="color:#999999">;</span> <span style="color:#708090">// TypeError for redeclaration.</span>
<span style="color:#0077aa">break</span><span style="color:#999999">;</span>
<span style="color:#999999">}</span></code></span>
let后跟一个函数传递的参数时将导致循环内部报错。
function go(n){
for (let n of n.a) { // TypeError: n is undefined
console.log(n);
}
}
go({a:[1,2,3]});
循环定义中的let作用域
循环体中是可以引用在for声明时用let定义的变量,尽管let不是出现在大括号之间.(注:该方法在 火狐 45.4.0 ,Centos7 下,报错 ReferenceError: can't access lexical declaration `i' before initialization)
<span style="color:#333333"><code class="language-js"><span style="color:#0077aa">var</span> i <span style="color:#a67f59">=</span> <span style="color:#990055">0</span><span style="color:#999999">;</span>
<span style="color:#0077aa">for</span> <span style="color:#999999">(</span><span style="color:#0077aa">let</span> i <span style="color:#a67f59">=</span> i<span style="color:#999999">;</span> i <span style="color:#a67f59"><</span> <span style="color:#990055">10</span><span style="color:#999999">;</span> i<span style="color:#a67f59">++</span><span style="color:#999999">)</span> <span style="color:#999999">{</span>
console<span style="color:#999999">.</span><span style="color:#dd4a68">log</span><span style="color:#999999">(</span>i<span style="color:#999999">)</span><span style="color:#999999">;</span>
<span style="color:#999999">}</span></code></span>
注:以上 let 声明的 i 将会变成 undefined;chrome 版本50.0.2661.102 (64-bit);推荐以下写法:
<span style="color:#333333"><code class="language-html">var i = 0;
for (let l = i; l < 10; l++) {
console.log(l);
}</code></span>
域作用规则
<span style="color:#333333"><code class="language-html">for (let expr1; expr2; expr3) statement</code></span>
在这个例子中,expr2, expr3, 和 statement 都是包含在一个隐含域块中,其中也包含了 expr1.
例子
let
对比 var
let的作用域是块,而var的作用域是函数
<span style="color:#333333"><code class="language-js"><span style="color:#0077aa">var</span> a <span style="color:#a67f59">=</span> <span style="color:#990055">5</span><span style="color:#999999">;</span>
<span style="color:#0077aa">var</span> b <span style="color:#a67f59">=</span> <span style="color:#990055">10</span><span style="color:#999999">;</span>
<span style="color:#0077aa">if</span> <span style="color:#999999">(</span>a <span style="color:#a67f59">===</span> <span style="color:#990055">5</span><span style="color:#999999">)</span> <span style="color:#999999">{</span>
<span style="color:#0077aa">let</span> a <span style="color:#a67f59">=</span> <span style="color:#990055">4</span><span style="color:#999999">;</span> <span style="color:#708090">// The scope is inside the if-block</span>
<span style="color:#0077aa">var</span> b <span style="color:#a67f59">=</span> <span style="color:#990055">1</span><span style="color:#999999">;</span> <span style="color:#708090">// The scope is inside the function</span>
console<span style="color:#999999">.</span><span style="color:#dd4a68">log</span><span style="color:#999999">(</span>a<span style="color:#999999">)</span><span style="color:#999999">;</span> <span style="color:#708090">// 4</span>
console<span style="color:#999999">.</span><span style="color:#dd4a68">log</span><span style="color:#999999">(</span>b<span style="color:#999999">)</span><span style="color:#999999">;</span> <span style="color:#708090">// 1</span>
<span style="color:#999999">}</span>
console<span style="color:#999999">.</span><span style="color:#dd4a68">log</span><span style="color:#999999">(</span>a<span style="color:#999999">)</span><span style="color:#999999">;</span> <span style="color:#708090">// 5</span>
console<span style="color:#999999">.</span><span style="color:#dd4a68">log</span><span style="color:#999999">(</span>b<span style="color:#999999">)</span><span style="color:#999999">;</span> <span style="color:#708090">// 1</span></code></span>
let
在循环中
可以用 let 来代替 var ,在 for 定义块中使用块级变量.
<span style="color:#333333"><code class="language-js"><span style="color:#0077aa">for</span> <span style="color:#999999">(</span><span style="color:#0077aa">let</span> i <span style="color:#a67f59">=</span> <span style="color:#990055">0</span><span style="color:#999999">;</span> i <span style="color:#a67f59"><</span> <span style="color:#990055">10</span><span style="color:#999999">;</span> i<span style="color:#a67f59">++</span><span style="color:#999999">)</span> <span style="color:#999999">{</span>
console<span style="color:#999999">.</span><span style="color:#dd4a68">log</span><span style="color:#999999">(</span>i<span style="color:#999999">)</span><span style="color:#999999">;</span> <span style="color:#708090">// 0, 1, 2, 3, 4 ... 9</span>
<span style="color:#999999">}</span>
console<span style="color:#999999">.</span><span style="color:#dd4a68">log</span><span style="color:#999999">(</span>i<span style="color:#999999">)</span><span style="color:#999999">;</span> <span style="color:#708090">// i is not defined</span></code></span>
非标准的 let 扩展
let块(
let
block)
let blocks 在 Gecko 44 中已经废除( bug 1167029) 。
let块
提供了一种在块的范围内获取变量的值,而不会影响块外面名字相同的变量的值的方法。
语法
<span style="color:#333333">let (var1 [= value1] [, var2 [= value2]] [, ..., varN [= valueN]]) block;</span>
描述
let 语句块为变量提供了局部作用域。它的作用是在单一代码块的词法范围内绑定零个或多个变量; 此外与普通语句块没有任何区别。需要特别注意的是, 在 let
语句块内使用 var 声明的变量,它的作用域与在 let 语句块之外声明没有区别;这样的变量仍然具有函数作用域。在使用 let
语句块时,必须使用花括号,否则会导致语法错误。
例子
<span style="color:#333333"><code class="language-js"><span style="color:#0077aa">var</span> x <span style="color:#a67f59">=</span> <span style="color:#990055">5</span><span style="color:#999999">;</span>
<span style="color:#0077aa">var</span> y <span style="color:#a67f59">=</span> <span style="color:#990055">0</span><span style="color:#999999">;</span>
<span style="color:#0077aa">let</span> <span style="color:#999999">(</span>x <span style="color:#a67f59">=</span> x <span style="color:#a67f59">+</span> <span style="color:#990055">10</span><span style="color:#999999">,</span> y <span style="color:#a67f59">=</span> <span style="color:#990055">12</span><span style="color:#999999">)</span> <span style="color:#999999">{</span>
console<span style="color:#999999">.</span><span style="color:#dd4a68">log</span><span style="color:#999999">(</span>x <span style="color:#a67f59">+</span> y<span style="color:#999999">)</span><span style="color:#999999">;</span> <span style="color:#708090">// 27</span>
<span style="color:#999999">}</span>
console<span style="color:#999999">.</span><span style="color:#dd4a68">log</span><span style="color:#999999">(</span>x <span style="color:#a67f59">+</span> y<span style="color:#999999">)</span><span style="color:#999999">;</span> <span style="color:#708090">// 5</span></code></span>
let 代码块的规则与 JavaScript 中其他类型的代码块相同。允许在块内通过 let 关键字声明局部变量。
作用域规则
使用 let
语句块绑定的变量,其作用域是 let
语句块本身,与任何其内部语句块的作用域一样,除非在这些内部语句块内又定义了同名的变量。
let
表达式( let expression)
let
expression 在 Gecko 41 已经废除(bug 1023609)。
let
表达式 可以将变量的作用域仅作用于一条语句。
语法
<span style="color:#333333">let (var1 [= value1] [, var2 [= value2]] [, ..., varN [= valueN]]) expression;</span>
例子
你可以在一条语句的范围中使用 let
关键字来设立变量:
<span style="color:#333333"><code class="language-js"><span style="color:#0077aa">var</span> a <span style="color:#a67f59">=</span> <span style="color:#990055">5</span><span style="color:#999999">;</span>
<span style="color:#0077aa">let</span><span style="color:#999999">(</span>a <span style="color:#a67f59">=</span> <span style="color:#990055">6</span><span style="color:#999999">)</span> console<span style="color:#999999">.</span><span style="color:#dd4a68">log</span><span style="color:#999999">(</span>a<span style="color:#999999">)</span><span style="color:#999999">;</span> <span style="color:#708090">// 6</span>
console<span style="color:#999999">.</span><span style="color:#dd4a68">log</span><span style="color:#999999">(</span>a<span style="color:#999999">)</span><span style="color:#999999">;</span> <span style="color:#708090">// 5</span></code></span>
作用域规则
给定一个 let
表达式:
<span style="color:#333333"><code class="language-html">let (decls) expr</code></span>
这里隐式创建了一个包围 expr 的语句块。
规范
Specification | Status | Comment |
---|---|---|
ECMAScript 2015 (6th Edition, ECMA-262) Let and Const Declarations |
Standard | Initial definition. Does not specify let expressions or let blocks. |
ECMAScript Latest Draft (ECMA-262) Let and Const Declarations |
Draft |
浏览器兼容性
We're converting our compatibility data into a machine-readable JSON format. This compatibility table still uses the old format, because we haven't yet converted the data it contains. Find out how you can help!
Feature | Chrome | Edge | Firefox (Gecko) | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|---|
Basic support | 41.0 | (Yes) | 44 (44) | 11 | 17 | ? |
Temporal dead zone | ? | (Yes) | 35 (35) | ? | ? | ? |
let expression |
未实现 | 未实现 | 未实现 | 未实现 | 未实现 | 未实现 |
let block |
未实现 | 未实现 | 未实现 | 未实现 | 未实现 | 未实现 |
Firefox-specific notes
- [1]: 只允许用在被
<script type="application/javascript;version=1.7">
包裹的代码块中 (或者更高的 版本version)。当心,无论如何, 作为一个非标准特性, 很有可能会打破其他浏览器的支持。 XUL 脚本标签实现这些特性不需要特殊的块。 请看 bug 932517和bug 932517。 - ES6 compliance for
let
in SpIderMonkey is tracked in bug 950547 and non-standard extensions are going to be removed in the future bug 1023609.
相关链接
var
const
- ES6 In Depth:
let
andconst
- Breaking changes in
let
andconst
in Firefox 44. - You Don't Know JS: Scope & Closures: Chapter 3: Function vs. Block Scope
文档标签和贡献者
标签:
此页面的贡献者: ssttii, SphinxKnight, jcguang, mathxlee, ywjco, zhangchen, yingying, frankfang1990, swfbarhr, xgqfrms-GitHub, mr.code, artificial, leafdog,yangzongjie, ZhiRui, ZhanghaoH, ChuckZhang, Go7hic, highsea, panhezeng, kemchenj, lunix01, dondevi, hang, Rococolate, Ende93, ouonet, ziyunfei, WangZishi,Junjie_Wei, teoli, nightire
最后编辑者: ssttii, Sep 16, 2018, 11:54:20 PM
原文链接:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/let