用來聲明變量,可是所聲明的變量只在let
命令所在的代碼塊內有效javascript
let不像var那樣會發生變量提高,因此必定要先聲明後使用。java
console.log(foo); //undefined console.log(bar); //報錯ReferenceError var foo = 2; let bar = 3;
ES6明確容許在塊級做用域中聲明函數。可是儘可能避免在塊級做用域內聲明函數,若是須要也要寫成函數表達式,而不是函數聲明語句。數組
在ES6中,塊級做用域之中,函數聲明的語句的行爲相似let,在塊級做用域以外不能被引用。瀏覽器
let實際上爲javascript新增了塊級做用域數據結構
外層做用域沒法讀取內層做用域的變量閉包
內層做用域能夠定義外層做用域的同名變量異步
塊級做用域實際上使得普遍運用的當即執行函數變得再也不必要了。函數
function f1() { let n =5; if(rue) {let n = 10;} console.log(n); //5,注意只能在f1這個做用域使用 }
javascript沒有塊級做用域,可是用let
聲明的變量能夠綁定到所在的任意做用域中,換句話說let爲其聲明的變量隱式的劫持了所在的塊做用域{...}
學習
var foo = true; if(foo) { let bar = foo * 2; bar = something(bar); console.log(bar); //bar只在foo做用域中有效 } console.log(bar); //ReferenceError
有興趣的能夠自行搜索瞭解一下TDZ(暫存死區)
,記得當時仍是看到阮大神的微博知道的~~指針
function bar(x = y; y = 2) { return [x, y]; } bar(); //報錯,此時至關於y未聲明的狀況下
let不容許在相同做用域內重複聲明同一個變量,不能在函數內部從新聲明參數。const也是這樣。
function(arg) {let arg; //報錯}
const
一樣能夠建立塊做用域變量,一樣只在聲明所在的塊級做用域中有效。但其值是固定的,不可更改,只讀。
一旦聲明變量,就必須當即初始化,不能留到之後賦值。
//只聲明不賦值就會報錯 const foo; //SyntaxError:
const聲明的變量也是不提高,一樣存在暫時性死區,只能在聲明的位置後面使用。
if(true) { console.log(MAX); //ReferenceError const MAX = 5; }
對於複合類型的變量,變量名不指向數據,而是指向數據所在的地址。const只保證變量名指向的地址不變,不保證該地址的數據保持不變。不能把foo指向另外一個地址。
const foo = {}; foo.prop = 123; foo.prop; //123 foo = {}; //TypeError:"foo" is read-only
瀏覽器環境指的是window對象 Node中指的是global對象
ES6中,var命令和function命令聲明的全局變量依舊是頂層對象的屬性,可是let和const以及class聲明的全局變量不屬於頂層對象的屬性。
var a = 1; window.a; //1 let b = 1; window.b; //undefined
嚴格模式下LHS查詢失敗時,並不會建立並返回一個全局變量,引擎會拋出同RHS查詢失敗時相似的
ReferenceError
異常若是RHS查詢到一個變量,嘗試對這個變量的值進行不合理的操做時,好比對一個非函數類型的值進行函數調用,或者引用null或undefined類型的值中的屬性,引擎會拋出另一中的異常
TypeError
ReferenceError
同做用域的判別失敗有關,TypeError
則表示做用域判別成功了,可是對結果的操做是非法的或者不合理的。
查找的目的是對變量進行賦值,那麼就會使用LHS查詢,若是目的是獲取變量的值,那麼就會使用RHS查詢。
像var a = 2
這樣的會被分解兩個步驟:(1)var a 會在做用域中聲明新變量,代碼執行前進行(2)a = 2 會查詢(LHS)變量a並對其進行賦值。
循環和閉包
每次迭代都生成一個新的做用域,使得延遲函數的回調能夠將新的做用域封閉在每一個迭代內部。
for(var i = 0; i <= 5; i++) { (functiong(j) { setTimeout(function timer() { console.log(a); }, 1000); })(i); }
var的循環,每一次循環都是新的i值覆蓋舊的i值,只有一個i,因此只輸出最後一個。
let的循環 每次循環都是一個新的變量i,多個i,因此會每一個都輸出,每次迭代都進行從新綁定,與閉包有關
異步
最大的特色就是能夠交出函數的執行權(即暫停執行)
函數名以前加星號.yield表示執行到此處,執行權將交給其餘協程。
function* gen(x) { var y = yield x + 2; return y; } var g = gen(1); g.next() //{value:3,done:false} //value是yield語句後面表達式的值,表示當前階段的值,done表示函數是否執行完畢,是否還有下一個階段。 g.next() //{value:undefined,done:true}
調用generator函數會返回一個內部指針g,執行它不會返回結果返回的是指針對象。調用指針的g的next方法,會移動內部指針,指向第一個遇到的yield語句即x+2處。
相似於數組可是成員的值都是惟一的,沒有重複的值。
var s = new Set([1,2,3,4,4]); [...s] //[1,2,3,4]
Set實例的方法
操做方法和遍歷方法
操做數據
(1) 操做方法
add:添加某個值,放回set結構自己
delete:刪除某個值返回一個布爾值,表示刪除是否成功
has(value):返回一個布爾值,表示該值是否爲set的成員
clear:清除全部成員,沒有返回值
s.add(2).add(3).add(2); s.size //2 s.has(1) //false s.has(2) //true s.has(3) //true s.delete(2); s.has(2) //false
(2) Array.from方法能夠將set數據結構轉爲數組
var items = new Set([1,2,3,4,5]); var array = Array.from(items);
(3) 擴展運算符...
也能夠將某些數據結構轉換一個數組
function foo() { var args = [...arguments]; } [...document.querySelectorAll("div")]
(4)數組去重的另外一種方法
function dedupe(array) { return Array.from(new Set(array)); } dedupe([1,1,2,3]) //[1,2,3]
遍歷操做
keys:返回鍵名的遍歷器
values:返回鍵值的遍歷器
entries:返回鍵值對的遍歷器
forEach:使用回掉函數遍歷每一個成員
隱式的強制轉換
3 + true; //4 NaN !== NaN; //true Null == undefined; //true
浮點數
0.1 + 0.2; //0.300000004 (8).toString(2); //"1000" parseInt("1001", 2); //9
數據類型
typeof null; //"object" typeof "hello"; //"string" var s = new String("hello"); typeof s; //"object" var s1 = new String("hello"); var s2 = new String("hello"); s1 === s2; //false s1 == s2; //false NaN !==NaN