let 語句聲明一個塊級做用域的本地變量,而且可選的將其初始化爲一個值。javascript
描述java
let 容許你聲明一個做用域或被限制在塊級中的變量、語句或者表達式。編程
與var不一樣的是,它聲明的變量只能是全局或者整個函數塊的。換句話,塊級 == { }閉包
爲何取‘let’這個名字。app
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聲明的做用域是塊。ide
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是最終值。此外咱們能夠經過將建立新元素的代碼移動到每一個循環的做用域來保持循環更清晰。ui
在程序或者函數的頂層,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會更加努力出好文~