2010-10-22 32 views
5

所以ECMAScript的5引入一些不兼容與ECMAScript的3.如何確保ES3程序在ES5引擎中運行?


Manyarticles已被寫入,說明this === null || this === undefined能夠在ES5嚴格模式

"use strict"; 
(function() { 
    alert(this); // null 
}).call(null); 

但是,什麼the standard真的建議是,ES5引擎還允許這種在非嚴格模式

15.3.4.3 ... 的thisArg值原封不動地作爲this值傳遞。這是從版本3發生的變化,其中undefinednull thisArg替換爲全局對象,ToObject應用於所有其他值,並且該結果作爲this值傳遞。

目前,IE9是真正實現ES5這種方式唯一的瀏覽器,而且事實證明,這可能break current scripts。大。


Annix E ES5 spec列出了許多其他不兼容性。

那麼確保我們久經考驗的ES3腳本能夠繼續無縫運行的最佳方式是什麼?某種自動化測試套件?我們需要手動測試嗎?

回答

4

自動化測試套件當然是一個好主意。

由於越來越多的實現實現了現在的ES5,在較新的瀏覽器中爲腳本/庫/應用程序運行測試套件是確保兼容性的好方法。

我有一個ES5 compatibility table,列出了一些更受歡迎的實現的支持級別。它並不詳盡,但它顯示了整體方向 - 最新的IE,WebKit,Chrome和Firefox都有相當不錯的ES5支持。對於完整的一致性測試,您可以隨時運行官方的ES5測試套件(爲方便起見,我已在線爲其提供right here)。

如果沒有測試套件(應該真的存在,因爲其他原因非常有用),您可以在更新的(符合ES5的)實現中運行腳本/庫/應用程序,並查看哪些方法可行,什麼失敗。

諮詢Annex E是另一種方式。請注意,儘管列表看起來相當大,但並不像看起來那麼糟糕。 ES5的目標之一是從ES3過渡到或多或少的無痛化,將更激進的變化轉移到選擇嚴格模式的領域。

該列表中的許多兼容性更改很可能不被注意。例如,在15.1.1中進行更改,其中全局undefined,NaNInfinity現在是隻讀的。考慮到理智的應用程序不會重新分配這些全球性質 - 除了錯誤 - 這種變化更多的是一個令人愉快的「錯誤捕獲器」而不是「應用程序斷開器」。

15.10.2.12的另一個點滴無辜的變化是空白字符類(\s)現在還匹配< BOM>(U+FEFF)字符。考慮到當前實現中的all the deviations(即使在ES3方面),在大多數應用程序中,這種更改可能不會引起注意。

但是,還有更危險的更改,如parseInt中的更改以及它如何不再將以0開頭的字符串視爲八進制值。 parseInt('010')不應再產生8(儘管一些實現選擇爲deliberately violate that behavior)。而且,依靠parseInt而沒有第二次「基數」的爭論從來不是一個好的做法。所以如果你的應用程序總是指定基數,沒有什麼可擔心的。

所以請參考附件E,在較新的實現中測試你的腳本(最好是多個),並且遵循最佳實踐。這是確保兼容性的好方法。

+0

你的測試套件是非常好的東西。但是,恐怕這對我的特殊情況無濟於事。基本上,我的公司需要確保我們的舊腳本不會在客戶的安裝中造成任何問題。我們在這裏討論數百和數百個腳本,手動檢查每一個功能看起來都很痛苦。 (「單元測試?那是什麼?」)目前,恐怕我們只是在等待錯誤報告。 – user123444555621 2010-10-23 07:41:42

+0

如何通過JSLint運行腳本?一個接一個,一點一點地。JSLint可能不會涵蓋所有對compat敏感的更改,但它肯定會讓你接近。它會警告parseInt w/o radix,以及關於屬性名稱的關鍵字(例如'({if:1})')等等。 – kangax 2010-10-23 20:08:34

+0

不幸的是,即使腳本在ES3中運行良好,JSLint也會報告數千個錯誤,偶爾會拒絕繼續(例如,當遇到'void'時)。事實上,過去我已經制作了一些JSLint模組,我也在考慮添加一些ES5的東西。但是,一些不兼容性(7.8.5/1,10.4.2,10.6/2,15.3.4.3,15.3.4.4,15.10.2.12)在分析時很難找到。 – user123444555621 2010-10-25 09:01:03

6

爲了記錄,提問者對ES5 15.3.4.3的解釋不正確。任何對ES5中非嚴格函數的調用都應該與ES3中的相同。全局對象仍然被傳遞到任何非空的或未定義的非嚴格函數作爲此值。

缺少的部分分析的是10.4.3「輸入功能碼」:

以下步驟當控制進入包含在函數對象˚F爲函數代碼的執行 上下文中執行,呼叫者 提供thisArg,和呼叫者提供argumentsList

  1. 如果在F驗證碼是嚴格的代碼,將ThisBinding設置爲thisArg
  2. 不然,如果thisArg未定義,設置ThisBinding 全局對象。
  3. ...

ES3指定的調用者負責代全局對象爲空或未定義此值。 ES5指定被調用者具有該責任(如果它不是嚴格的模式功能)。對於非嚴格的代碼,這不是一個可觀察到的差異。規格更改僅在被調用者是嚴格功能時才起作用。

+0

Typo:「未定義爲值」 – 2012-02-17 21:51:29

+0

@ AxelRauschmayer-ES5必須以這種方式工作,因爲調用者不一定知道被調用者是否處於嚴格模式。所以從調用中傳遞* thisArg *並讓被調用者進行排序是有道理的。 :-) – RobG 2014-10-13 03:41:20

相關問題