<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # 3. 一個JavaScript:在 ECMAScript 6 中避免版本化 > 本章地址:https://exploringjs.com/es6/ch_one-javascript.html 給一門語言添加新特性的最好方式是什么?本章描述了 ECMAScript 6 使用的方式。它被稱作 \*一個 JavaScript \*,因為避免了版本化。 ## 3.1 版本化 原則上,語言的一個新版本是一個清理的機會,可以清理過時的特性或者改變特性的工作方式。這意味著新的代碼在語言的舊的實現中無法工作,老的代碼在新的實現中無法工作。每段代碼都和特定的語言版本關聯。針對兩個不同語言版本寫兩種不同代碼是很常見的。 首先,你可以使用一種“用所有還是什么都不用”的方式:如果一個代碼庫需要使用新的語言版本,就必須徹底升級。Python 在從 Python 2 升級到 Python 3 的時候就是這樣的。這樣的話有個問題,將已有的代碼庫一次性全部升級可能是做不到的,尤其是代碼庫很大的時候。而且,這種方式對于 web 來說是不可行的,因為總是有老代碼,而且 JavaScript 引擎會自動升級。 第二,你可以讓一個代碼庫包含在多個語言版本都可運行的代碼,通過根據版本切換代碼的方式。你可以通過一個專用的[互聯網媒體類型](http://en.wikipedia.org/wiki/Internet_media_type)標記 ECMAScript 6 的代碼。這樣的媒體類型可以和一個 HTTP 頭關聯在一起: ``` Content-Type: application/ecmascript;version=6 ``` 也可以和`<script>`元素中的`type`屬性關聯在一起(`type`[默認值](http://www.w3.org/TR/html5/scripting-1.html#attr-script-type)是`text/javascript`): ```html <script type="application/ecmascript;version=6"> ··· </script> ``` 這是在代碼之外指定版本。另一種方案是在代碼內指定版本。例如,將下面的代碼放在 JavaScript 文件的第一行: ~~~js use version 6; ~~~ 兩種標記的方法都很容易產生問題:外部版本標記法很脆弱,容易丟失;內部版本標記法又會使代碼顯得雜亂。 一個更根本的問題是,針對不同的語言版本,要維護不同的執行引擎。這就引起了一些問題: * 引擎變得臃腫,因為要實現所有版本的語義。對于分析語言的工具也帶來了同樣的問題(比如類型檢測, JSLint )。 * 開發者需要記住版本之間的不同點。 * 代碼變得更加難以重構,因為在移動代碼的時候需要考慮語言版本的問題。 因此,應該避免版本化,尤其是 JavaScript 和 web 。 ### 3.1.1 非版本化的升級 但是我們如何解決版本化的問題?通過一直向后兼容。這意味著我們必須放棄一些野心,比如清理 JavaScript :我們不能引入破壞性改變。向后兼容意味著不要移除特性,也不要修改特性。原則是:“不要破壞 web ”。 然而,我們可以添加新的特性,并且使已有的特性更加強大。 因此,對于新的引擎不需要版本化管理了,因為仍然可以運行老的代碼。 David Herman 稱這種避免版本化的方法為[`一個 JavaScript ( One JavaScript(1JS) [1] )`](http://exploringjs.com/es6/ch_one-javascript.html#one-js_1),因為它使 JavaScript 避免分成幾種不同的版本或模式。正如我們將要看到的,由于嚴格模式,使得 1JS 甚至移除了一些已有的分裂。 一個 JavaScript ( One JavaScript )不是說你必須完全放棄語言清理。你可以引入新的干凈的特性,而不是清理掉已有的特性。其中一個例子就是`let`,它聲明了塊級范圍的變量,是`var`的一個升級版本。它并不取代`var`,而是作為高級可選項一直和`var`并存。 某一天,甚至可能清除掉沒人使用的特性。一些 ES6 特性是在調查過 web 上的 JavaScript 代碼才設計的。舉兩個例子: * `let`聲明很難添加到非嚴格模式,因為`let`在這種模式下是保留字。使用`let`關鍵字看起來像是合法 ES5 代碼的形式是: ```js let[x] = arr; ``` 經研究得出,在 web 上沒人以這種方式在非嚴格模式下使用變量`let`。這使得 TC39 將`let`添加進了嚴格模式。在本章后面講述了這是如何做的。 * 函數聲明確實偶爾會在非嚴格模式下的代碼塊中出現,這就是為什么 ES6 規范描述了 web 瀏覽器可以采用的措施來確保這樣的代碼不會被破壞。后面詳細講解([3.2.3 松散模式下的塊級函數聲明](#))。 ## 3.2 嚴格模式與 ECMAScript 6 ECMAScript 5 引入 [Strict mode](http://speakingjs.com/es5/ch07.html#strict_mode)來清理語言,在文件或者函數的第一行放入下面的內容就可以開啟嚴格模式: ```js 'use strict'; ``` 嚴格模式引入了三種破壞性的改變: * 語法改變:一些之前合法的語法在嚴格模式下面是不允許的。例如: * 禁止`with`語句。它允許使用者添加任何對象到變量作用域鏈,這會減緩程序的執行速度,并且很難指出某個變量指向哪里。 * 刪除一個獨立的標識符(一個變量,而不是一個屬性)是不允許的。 * 函數只能在作用域的頂層聲明。 * 更多的保留字: implements interface let package private protected public static yield 。 * 更多種類的錯誤。例如: * 給一個未聲明的變量賦值會拋出`ReferenceError`。在非嚴格模式下,這樣干就會創建一個全局變量。 * 修改只讀的屬性(比如字符串的長度屬性)會拋出`TypeError`。在非嚴格模式下,不會產生任何效果。 * 不同的語義:在嚴格模式下,一些語法結構表現得不一樣。例如: * `arguments`不再隨著當前參數值的改變而改變。 * 在非方法的函數中`this`是`undefined`。在非嚴格模式下,它指向全局對象(`window`),也就是說如果調用一個構造器的時候沒有使用`new`,就會創建一些全局變量。 嚴格模式是一個很好地說明了版本化是棘手的:即便能夠制作一個干凈版本的 JavaScript ,也很難被大家接受。主要原因是破壞了一些現存的代碼,降低了執行速度,并且加入到文件中也很麻煩(更不用說交互的命令行)。我喜歡嚴格模式這種想法,但卻很少使用它。 ### 3.2.1 支持松散( sloppy 非嚴格)模式 一個 JavaScript (One JavaScript) 意味著我們不能放棄松散模式:此模式將會繼續存在(例如在 HTML 屬性中)。因此,我們不能基于嚴格模式來構建 ECMAScript 6 ,必須同時在嚴格模式和非嚴格模式(又稱為松散模式)下添加特性。否則,嚴格模式就會成為一個不同的語言版本,就退回了版本化的方式。很不幸,有兩個特性很難引入松散模式:`let`聲明和塊級函數聲明。讓我們看看為什么很難引入和如何引入。 ### 3.2.2 松散模式中的`let`聲明 `let`使你能夠聲明塊級變量。這很難被引入到松散模式,因為`let`僅在嚴格模式下是保留字。也就是說,下面兩條語句在 ES5 的松散模式下是合法的: ```js var let = []; let[x] = 'abc'; ``` 在 ECMASCript 6 的嚴格模式下,第一行就會拋出異常。因為使用了`let`作為變量名。然后第二行會被解析為一個`let`變量聲明(使用解構)。 在 ECMAScript 6 的松散模式下,第一行不會拋出異常,但是第二行依然被解析為一個`let`聲明。這種使用`let`的方式在 web 上是極少見的,因此 ES6 可以直接這樣來解析。 ES5 松散模式下的其他`let`聲明的書寫方式不會被誤解: ```js let foo = 123; let {x,y} = computeCoordinates(); ``` ### 3.2.3 松散模式下的塊級函數聲明 ECMAScript 5 嚴格模式禁止在塊中聲明函數,在松散模式下,規范卻允許這么做,但是沒說這樣會發生什么。因此,很多 JavaScript 實現都支持塊級函數聲明,但是處理方式是不一樣的。 ECMAScript 6 想要塊中的函數聲明本地化(即該函數的作用域救在該塊中)。作為 ES5 嚴格模式的擴展,這是沒問題的,但是破壞了一些松散模式的代碼。因此, ES6 為瀏覽器提供了“[web 遺留的兼容語義](http://www.ecma-international.org/ecma-262/6.0/#sec-block-level-function-declarations-web-legacy-compatibility-semantics)”,允許塊中的函數聲明在函數作用域中存在。 ### 3.2.4 其它關鍵字 標識符`yield`和`static`僅在 ES5 的嚴格模式下是保留字。 ECMAScript 6 使用上下文相關的語法規則來使它們在松散模式下起作用: * 在松散模式下,`yield`僅在生成器函數中是保留字。 * `static`現在僅用于類字面量中,類字面中默認就是嚴格的(見下文)。 ### 3.2.5 **隱式的嚴格模式** 在 ECMAScript 6 中,模塊體和類體 默認就是嚴格模式的–沒必要使用`use strict`標記。考慮到我們所有的代碼都將會位于模塊中, ECMAScript 6 有效地將整個語言升級到了嚴格模式。 其它結構體(比如箭頭函數和生成器函數)本來也應該隱式地為嚴格模式。但是考慮到通常情況下這些結構都很小,在非嚴格模式下使用它們就會造成代碼中兩種模式的碎片化切換。類,尤其是模塊一般是足夠大的,這樣一來就可以忽略碎片化的代碼片段問題了。 > 那么需要我們去留心 嚴格模式 下的一些約束,會發生什么變化。 ### 3.2.6 無法修復的東西 一個 JavaScript 的缺陷(The downside of One JavaScript)就是無法修復已有的怪異行為,尤其是下面這兩個。 第一個,`typeof null`應該返回字符串`null`而不是`object`。但是修正這個就會破壞已有的代碼。另一方面,給新種類的操作數添加新的操作結果是沒問題的,因為當前的 JavaScript 引擎對于一些宿主對象已經會返回自定義的值。 ECMAScript 6 的 Symbol 就是一個例子: ```js > typeof Symbol.iterator 'symbol' ``` 第二個,全局對象(瀏覽器中的`window`對象)不應該在變量作用域鏈。但是現在修正這個也太晚了。但是至少,在模塊中不會處于全局作用域下,并且`let`永遠不會創建全局對象屬性,甚至在全局作用域下使用也不會。 ``` let letStr = 'letStr'; console.log(window.letStr) // undefined var varStr = 'varStr'; console.log(window.varStr) // “varStr” ``` ## 3.3 ES6中的突破性變化(Breaking changes) ECMAScript 6確實引入了一些微小的突破性變化(你可能不會遇到)。它們列在兩個附件(annexes)中: - [附件D:2015年電子手冊中可能對兼容性產生影響的更正和澄清](http://www.ecma-international.org/ecma-262/6.0/#sec-corrections-and-clarifications-in-ecmascript-2015-with-possible-compatibility-impact) - [附件E:引入與以前版本不兼容的添加和更改](http://www.ecma-international.org/ecma-262/6.0/#sec-additions-and-changes-that-introduce-incompatibilities-with-prior-editions) ## 3.4 總結 一個 JavaScript 意思就是使 ECMAScript 6 完全地向后兼容,很高興這獲得了成功。尤其是模塊隱式就是嚴格模式的(這樣一來我們大部分的代碼都會處于嚴格模式下)。 在短期內,對于制定 ES6 規范和引擎實現來說,給嚴格模式和松散模式添加 ES6 的語法結構會耗費更多的精力。從長遠來看,規范和引擎將會受益于語言不分叉(更少的膨脹等等)。開發人員會立即從一個 JavaScript 中獲得好處,因為開始使用 ECMAScript 6 變得更加容易。 ## 3.5 深入閱讀 [1] 原始的 1 JS 提案(警告:已過時): “[ES6 doesn’t need opt-in](http://esdiscuss.org/topic/es6-doesn-t-need-opt-in)”,作者 David Herman 。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看