你會使用ES6 ,但這幾點你可能不知道,感受身體被掏空!

let 的使用

咱們知道 let 主要有三個特性:javascript

  1. let 聲明的變量的做用域是塊級的 (es5中只有全局和函數做用域)
  2. let 不能重複聲明已存在的變量;
  3. let 有暫時死區,不會被提高。

咱們早期面試的時候,常常會考的一道題目是:java

// 代碼段1
var liList = document.querySelectorAll('li') // 共5個li
for( var i=0; i<liList.length; i++){
  liList[i].onclick = function(){
    console.log(i)
  }
}

你們都知道依次點擊 li 會打印出 5 個 5。若是把 var i 改爲 let i,就會分別打印出 0、一、二、三、4:es6

// 代碼段2
var liList = document.querySelectorAll('li') // 共5個li
for( let i=0; i<liList.length; i++){
  liList[i].onclick = function(){
    console.log(i)
  }
}

然而,你會發現 for( let i=0; i<liList.length; i++),這樣聲明 i 的做用域是哪一個?這邊直接跟你說吧,i 的做用域只在for()括號裏面,因此代碼中依然只聲明瞭一個 i,在 for 循環結束後,i 的值仍是會變成 5 纔對。這裏可能就說明有一部分的人對 let 理解有誤了。面試

因而咱們方方老師大佬去看 MDN 的例子,發現雞賊的 MDN 巧妙地避開了這個問題,它的例子是這樣的:segmentfault

clipboard.png

它直接在另外聲明瞭一個 j 來保存, 爲何不直接用 i 呢?MDN 爲了簡化知識,隱瞞了什麼?函數

通過咱們方方老師大佬飢渴精神,不斷的查資料,最後他總結這麼幾句本身的理解:學習

  1. for( let i = 0; i< 5; i++) 這句話的圓括號之間,有一個隱藏的做用域
  2. for( let i = 0; i< 5; i++) { 循環體 } 在每次執行循環體以前,JS 引擎會把 i 在循環體的上下文中從新聲明及初始化一次。

也就是說上面的代碼段2能夠近似近似近似地理解爲:es5

// 代碼段3
var liList = document.querySelectorAll('li') // 共5個li
for( let i=0; i<liList.length; i++){
  let i = 隱藏做用域中的i // 看這裏看這裏看這裏
  liList[i].onclick = function(){
    console.log(i)
  }
}

那樣的話,5 次循環,就會有 5 個不一樣的 i,console.log 出來的 i 固然也是不一樣的值。spa

再加上隱藏做用域裏的 i,一共有 6 個 i。code

這就是 MDN 加那句 let j = i 的緣由:方便新人理解。

總得來講就是 let/const 在與 for 一塊兒用時,會有一個 perIterationBindings 的概念(一種語法糖)。

let 到底有沒有提高

以前我寫過一篇 《你一度模糊的javascript執行上下文詳解》, 說到js在一段<script>或者一個函數,都會生成一個執行上下文,就是js會先把聲明的變量都 拿出來,並初始化爲 undefined,這就解釋了爲何在 var x = 1 以前 console.log(x) 會獲得 undefined。

那let 的執行上下文,會是怎麼樣的呢?假設代碼以下:

{
  let x = 1
  x = 2
}

咱們只看 {} 裏面的過程:

  1. 找到全部用 let 聲明的變量,在環境中「建立」這些變量
  2. 開始執行代碼(注意如今尚未初始化)
  3. 執行 x = 1,將 x 「初始化」爲 1(這並非一次賦值,若是代碼是 let x,就將 x 初始化爲 undefined)
  4. 執行 x = 2,對 x 進行「賦值」

這就解釋了爲何在 let x 以前使用 x 會報錯:

let x = 'global'
{
  console.log(x) // Uncaught ReferenceError: x is not defined
  let x = 1
}

緣由有兩個:

  1. console.log(x) 中的 x 指的是下面的 x,而不是全局的 x
  2. 執行 log 時 x 還沒「初始化」,因此不能使用(也就是所謂的暫時死區)

看到這裏,你應該明白了 let 到底有沒有提高:

  1. let 的「建立」過程被提高了,可是初始化沒有提高。
  2. var 的「建立」和「初始化」都被提高了。
  3. function 的「建立」「初始化」和「賦值」都被提高了。

get 與 set 的方法

  1. Get指讀取屬性時調用的函數
  2. Set指寫入屬性時調用的函數。

有這麼一道題是這樣的:有沒有可能存在一個變量同時知足下列條件:

a === 1 && a === 2 && a ===3

有的人可能會以爲這怎麼可能變成立呢,一個變量兩個值?這邊就要引入咱們set的方法了,咱們能夠在window,設置一個屬性a ,以下定義:

var i = 0;

Object.defineProperty(window, 'a',{
    get:function() {
        i += 1;
        return i;
    },
})

經過在window定義一個a,而後每次訪問a的 i 的值會加做爲a的值返回,因此咱們在控制檯輸入:

clipboard.png

固然這個除了面試感受沒啥軟用,但這能告訴你 get, set有什麼用。

Symbol的巧用

咱們知道:ES 6 引入了一個新的數據類型 Symbol, Symbol 能夠建立一個獨一無二的值(但並非字符串)。

假如如今有一個對象,裏面有一個私有屬性,只能本身內部使用,外部調用不到,這時咱們能夠利用 Symbol來作:以下:

{
    let a = Symbol();
    let obj = {
        name: '小智',
        age: 18,
        [a]: '這個是私有屬性'
    }
    window.obj = obj;
}

clipboard.png

以下,我有在外部無語你怎麼用,都是調用不到 「這個是私有屬性」,你可能會說這個有啥用,我只能回答你裝x用的,面試可能也會問你 咱們如何弄一個隱藏屬性呢?答案就是 Symbol ,滿婚滿婚滿婚。

以上,就是 Symbol 的簡述,更詳細更權威的知識參考下面的自學連接。

MDN: Symbol - JavaScript
阮一峯:ECMAScript 6入門

參考:

我用了兩個月的時間才理解 let

一個笨笨的碼農,個人世界只能終身學習

相關文章
相關標籤/搜索