let 語句聲明一個塊級作用域的本地變量,並且可選的將其初始化為一個值。
描述
let 允許你聲明一個作用域或被限制在塊級中的變量、語句或者表達式。
與var不同的是,它聲明的變量只能是全局或者整個函數塊的。換句話,塊級 == { }
為什么取‘let’這個名字。
1 Let is a mathematical statement that was adopted by early programming languages like Scheme and Basic. 2 Variables are considered low level entities not suitable for higher levels of abstraction, 3 thus the desire of many language designers to introduce similar but more powerful concepts like in Clojure, F#, Scala, 4 where let might mean a value, or a variable that can be assigned, but not changed, 5 which in turn lets the compiler catch more programming errors and optimize code better. 6 JavaScript has had var from the beginning, so they just needed another keyword, 7 and just borrowed from dozens of other languages that use let already as a traditional keyword as close to var as possible, 8 although in JavaScript let creates block scope local variable instead.
1 Let是一個數學聲明,是采用於早期的編程語言如Scheme和Basic。 2 變量被認為是不適合更高層次抽象的低級實體,因此許多語言設計者希望引入類似但更強大的概念, 3 如在Clojure、f#、Scala,let可能意味着一個值,或者一個變量可以賦值,但不能被更改, 4 這反過來使編譯器能夠捕獲更多的編程錯誤和優化代碼更好。 5 javascript從一開始就有var,所以他們只是需要另一個關鍵字,並只是借用了其他數十種語言, 6 使用let已經作為一個傳統的盡可能接近var的關鍵字,雖然在javascript 中 let只創建塊范圍局部變量而已。
作用域規則
let 聲明的變量只是在其聲明的塊或者子塊中可用,這一點,與var相似。二者的主要區別在於var聲明的變量的作用域是整個封閉函數,而let聲明的作用域是塊。
1 function varTest() { 2 var x = 1; 3 if (true) { 4 var x = 2; // 同樣的變量! 5 console.log(x); // 2 6 } 7 console.log(x); // 2 8 } 9 10 function letTest() { 11 let x = 1; 12 if (true) { 13 let x = 2; // 不同的變量 14 console.log(x); // 2 15 } 16 console.log(x); // 1 17 }
簡化內部函數代碼
當用到內部函數時候,let 會讓你的代碼更加簡潔。
1 var list = document.getElementById('list'); 2 3 for (let i = 1; i <= 5; i++) { 4 let item = document.createElement('li'); 5 item.appendChild(document.createTextNode('Item ' + i)); 6 7 item.onclick = function(ev) { 8 console.log('Item ' + i + ' is clicked.'); 9 }; 10 list.appendChild(item); 11 } 12 13 // to achieve the same effect with 'var' 14 // you have to create a different context 15 // using a closure to preserve the value 16 for (var i = 1; i <= 5; i++) { 17 var item = document.createElement('li'); 18 item.appendChild(document.createTextNode('Item ' + i)); 19 20 (function(i){ 21 item.onclick = function(ev) { 22 console.log('Item ' + i + ' is clicked.'); 23 }; 24 })(i); 25 list.appendChild(item); 26 }
以上示例的工作原理是因為(匿名)內部函數的五個實例引用了變量i的五個不同實例。注意,如果將let 替換為 var, 則它將無法正常工作,因為所有內部函數都將返回相同的i,6是最終值。此外我們可以通過將創建新元素的代碼移動到每個循環的作用域來保持循環更清晰。
在程序或者函數的頂層,let 並不會像var 一樣在全局對象上創建一個屬性,比如:
1 var x = "apple"; 2 let y = "apple"; 3 console.log(this.x); //'apple' 4 console.log(this.y); //undefined
模仿私有接口
在處理構造函數的時候,可以通過let 綁定來共享一個或者多個私有成員,而不使用閉包:
1 var Thing; 2 { 3 let privateScope = new WeakMap(); 4 let counter = 0; 5 6 Thing = function(){ 7 this.someProperty = 'foo'; 8 privateScope.set(this, { 9 hidden: ++counter, 10 }); 11 }; 12 13 Thing.prototype.showPublic = function(){ 14 return this.someProperty; 15 }; 16 17 Thing.prototype.showPrivate = function(){ 18 return privateScope.get(this).hidden; 19 }; 20 } 21 22 console.log(typeof privateScope); //undefined 23 24 var thing = new Thing(); 25 console.log(thing); //Thing { someProperty: 'foo' } 26 console.log(thing.showPublic()); //foo 27 console.log(thing.showPrivate()); //1
let 暫存死區的錯誤
在相同的函數或者塊級作用域內重新聲明同一個變量會引發SyntaxError
1 if (x) { 2 let foo; 3 let foo; // TypeError thrown. 4 }
所以在同一個塊區,以let聲明的變量,只能聲明一次。
其他情況
當在塊中使用時,let 將變量的作用域限制為該塊。注意var 的作用域在它被聲明的函數內區別。
1 var a = 1; 2 var b = 2; 3 4 if(a === 1){ 5 var a = 11; 6 let b = 22; 7 8 console.log(a); // 11 9 console.log(b); // 22 10 } 11 console.log(a); // 11 12 console.log(b); // 2
總之,let 的作用域是自己最近的{}
如果你覺得此文對你有一點小小的幫助,可以贊助作者哦,Mike會更加努力出好文~