<b>本文講的是使用 ES6 寫更好的 JavaScript part I:廣受歡迎的新特性,</b>
在 ES2015 規範敲定并且 Node.js 增添了大量的函數式子集的背景下,我們終于可以拍着胸脯說:未來就在眼前。
. . . 我早就想這樣說了
這篇文章将會講到三個相當流行的 ES2015 特性,并且已經在 Node 中支援了了:
用 <code>let</code> 和 <code>const</code> 聲明塊級作用域;
箭頭函數;
簡寫屬性和方法。
讓我們馬上開始。
作用域 是你程式中變量可見的區域。換句話說就是一系列的規則,它們決定了你聲明的變量在哪裡是可以使用的。
大家應該都聽過 ,在 JavaScript 中隻有在函數内部才會創造新的作用域。然而你建立的 98% 的作用域事實上都是函數作用域,其實在 JavaScript 中有三種建立新作用域的方法。你可以這樣:
建立一個函數。你應該已經知道這種方式。
建立一個代碼塊。如果你用的是 ES2015,在一段代碼塊中用 <code>let</code> 或者 <code>const</code> 聲明的變量會限制它們隻在這個塊中可見。這叫做_塊級作用域_.
一個_代碼塊_就是你用花括号包起來的部分。 <code>{ 像這樣 }</code>。在 <code>if</code>/<code>else</code> 聲明和 <code>try</code>/<code>catch</code>/<code>finally</code> 塊中經常出現。如果你想利用塊作用域的優勢,你可以用花括号包裹任意的代碼來建立一個代碼塊
考慮下面的代碼片段。
還有些要強調的
注意 <code>foobar</code> 在 <code>if</code> 塊之外是不可見的,因為我們沒有用<code>let</code> 聲明;
我們可以在任何地方使用 <code>foo</code> ,因為我們用 <code>var</code> 定義它為全局作用域可見;
我們可以在 <code>baz</code> 内部任何地方使用 <code>bar</code>, 因為 <code>var</code>-聲明的變量是在定義的整個作用域内都可見。
用 let or const 聲明的變量不能在定義前調用。換句話說,它不會像 <code>var</code> 變量一樣被編譯器提升到作用域的開始處。
<code>const</code> 與 <code>let</code> 類似,但有兩點不同。
必須 給聲明為 <code>const</code> 的變量在聲明時指派。不可以先聲明後指派。
不能 改變<code>const</code>變量的值,隻有在建立它時可以給它指派。如果你試圖改變它的值,會得到一個 <code>TyepError</code>。
我們已經用 <code>var</code> 将就了二十多年了,你可能在想我們_真的_需要新的類型聲明關鍵字嗎?(這裡作者應該是想表達這個意思)
問的好,簡單的回答就是-- 不, 并不 真正 需要。但在可以用<code>let</code> 和 <code>const</code> 的地方使用它們很有好處的。
<code>let</code> 和 <code>const</code> 聲明變量時都不會被提升到作用域開始的地方,這樣可以使代碼可讀性更強,制造盡可能少的迷惑。
它會盡可能的限制變量的作用域,有助于減少令人迷惑的命名沖突。
這樣可以讓程式隻有在必須重新配置設定變量的情況下重新配置設定變量。 <code>const</code> 可以加強常量的引用。
另一個例子就是 <code>let</code> 在 <code>for</code> 循環中的使用:
在 <code>for</code>循環中使用 <code>var</code> 聲明的計數器并不會 真正 把計數器的值限制在本次循環中。 而 <code>let</code> 可以。
<code>let</code> 在每次疊代時重新綁定循環變量有很大的優勢,這樣每個循環中拷貝 自身 , 而不是共享全局範圍内的變量。
第一層循環會和你想象的一樣工作。而下面的會每秒輸出 "I've waited 6 seconds!"。
好吧,我選擇狗帶。
JavaScript 的 <code>this</code> 關鍵字因為總是不按套路出牌而臭名昭著。
在 <code>introduce</code> 裡, <code>this.name</code> 是 <code>undefined</code>。在回調函數外面,也就是 <code>forEach</code> 中, 它指向了 <code>polyglot</code> 對象。在這種情形下我們總是希望在函數内部 <code>this</code> 和函數外部的 <code>this</code> 指向同一個對象。
這些規則中沒有一個是關于查找 this 所描述的“附近作用域”的;也就是說并沒有一個确切的方法可以讓 JavaScript 引擎能夠基于包裹作用域來定義 this的含義。
這就意味着當引擎查找 <code>this</code> 的值時,可以找到值,但卻和回調函數之外的不是同一個值。有兩種傳統的方案可以解決這個問題。
在函數外面吧 <code>this</code> 儲存到一個變量中,通常取名 <code>self</code>,并在内部函數中使用;或者
以上兩種辦法均可生效,但會産生副作用。
另一方面,如果内部函數 沒有 設定它自己的 <code>this</code> 值,JavaScript 會像查找其它變量那樣查找 <code>this</code> 的值:通過周遊父作用域直到找到同名的變量。這樣會讓我們使用附近作用域代碼中的 this 值,這就是著名的 詞法 <code>this</code> 。
如果有樣的特性,我們的代碼将會更加的清晰,不是嗎?
在 ES2015 中,我們有了這一特性。箭頭函數 不會 綁定 <code>this</code> 值,允許我們利用詞法綁定 <code>this</code> 關鍵字。這樣我們就可以像這樣重構上面的代碼了:
. . . 這樣就會按照我們想的那樣工作了。
箭頭函數有一些新的文法。
ES2015 提供了在對象上定義屬性和方法的一些新方式。
在 JavaScript 中, method 是對象的一個有函數值的屬性:
在ES2015 中,我們可以這樣簡寫:
注意你也可以使用生成器去定義方法。隻需要在函數名前面加一個星号 (*)。
這些叫做 方法定義 。和傳統的函數作為屬性很像,但有一些不同:
隻能 在方法定義處調用 <code>super</code> ;
不允許 用 <code>new</code> 調用方法定義。
ES6 還引入了 簡寫 和 推導屬性 。
如果對象的鍵值和變量名是一緻的,那麼你可以僅用變量名來初始化你的對象,而不是定義備援的鍵值對。
兩中文法都以 <code>foo</code> 和 <code>bar</code> 鍵值指向 <code>foo</code> and <code>bar</code> 變量。 後面的方式語義上更加一緻;這隻是個文法糖。
這裡我們建立并傳回了一個 <code>publicAPI</code> 對象,鍵值 <code>foo</code> 指向 <code>foo</code> 方法,鍵值 <code>bar</code> 指向 <code>bar</code> 方法。
這是 不常見 的例子,但 ES6 允許你用表達式做屬性名。
最後,我想提一下 <code>get</code> 和 <code>set</code> 方法,它們在 ES5 中就已經支援了。
使用 getters 時要記得下面這些:
Getters 不接受參數;
屬性名不可以和 getter 函數重名;
可以用 <code>Object.defineProperty(OBJECT, "property name", { get : function () { . . . } })</code> 動态建立 getter
作為最後這點的例子,我們可以這樣定義上面的 getter 方法:
除了 getters,還有 setters。像平常一樣,它們通過自定義的邏輯給對象設定屬性。
上面講的關于 getters 的也同樣适用于 setters ,但有一點不同:
getter 不接受 參數, setters 必須 接受 正好一個 參數。
破壞這些規則中的任意一個都會抛出一個錯誤。
既然 Angular 2 正在引入 TypeCript 并且把 <code>class</code> 帶到了台前,我希望 <code>get</code> and <code>set</code> 能夠流行起來. . . 但還有點希望它們不要起來。
未來的 JavaScript 正在變成現實,是時候把它提供的東西都用起來了。這篇文章裡,我們浏覽了 ES2015 的三個很流行的特性:
<code>let</code> 和 <code>const</code> 帶來的塊級作用域;
箭頭函數帶來的 <code>this</code> 的詞法作用域;
簡寫屬性和方法,以及 getter 和 setter 函數的回顧。
<b></b>
<b>原文釋出時間為:2016年06月12日</b>
<b>本文來自雲栖社群合作夥伴掘金,了解相關資訊可以關注掘金網站。</b>