文章目錄javascript
一年半以前我寫了一篇《關於瀏覽器模式和文本模式的困惑》,介紹了 IE8+ 特有的瀏覽器模式(Browser Mode)和文本模式(Document Mode),以及個人測試和微軟文檔有出入的部分。其中有一些沒有提到的內容,本文繼續討論。 html
判斷真正的 IE 版本
不少 JS 框架都經過 UA 判斷 IE 的版本。對於 IE6,這種作法沒問題( IE6 沒有瀏覽器模式的概念,也沒有其它 IE 能夠把瀏覽器模式改成 IE6;IE7 雖然也沒有瀏覽器模式,但 IE8+ 能夠把瀏覽器模式設置爲 IE7 模式)。可是從 IE8 開始引入的瀏覽器模式會產生不一樣的 UA。例如,IE9 有這些:html5
瀏覽器模式 | navitor.userAgent | 默認文本模式 |
---|---|---|
IE7 | MSIE 7.0 | IE7標準 |
IE8 | MSIE 8.0 && Trident/4.0 | IE8標準 |
IE9 | MSIE 9.0 && Trident/5.0 | IE9標準 |
IE9兼容性 | MSIE 7.0 && Trident/5.0 | IE7標準 |
若是僅經過 UA 中的「MSIE X.0」來判斷,會獲得 IE7~9 三種不一樣結果。java
實際上,對於 IE8+,根據 UA 字符串只能肯定當前是不是兼容性視圖。由於兼容性視圖的 UA 中,IE 版本和 Trident 版本不匹配。例如 UA 裏同時有「MSIE 7.0」和「Trident/6.0」,說明瀏覽器模式確定是 IE10兼容性。這是由於 IE8 纔開始給 UA 加上 Trident 信息,而 Trident/6.0 是 IE10 所特有。瀏覽器
除此以外,上面 IE7 和 IE8 這兩種瀏覽器模式,UA 和跟真正的 IE7 或 IE8 沒有任何區別,根據 UA 徹底沒辦法區分。甚至連 IE9 模式,咱們也沒法確認這是 IE9 瀏覽器的默認模式,仍是 IE10 瀏覽器的 IE9 模式。框架
下面來看看文本模式,依然用 IE9 測試。選擇不一樣的文本模式,documentMode 的值也不同。ide
文本模式 | document.documentMode |
---|---|
IE7標準 | 7 |
IE8標準 | 8 |
IE9標準 | 9 |
IE5怪異(Quirks) | 5 |
document.documentMode 這個 JS 屬性是 IE8 引入的,對於 IE8+ 不管選擇什麼文本模式,這個屬性都有值。而 IE6 和 IE7 下,這個屬性是 undefined。根據這一點,能夠結合 UA 判斷出用戶使用的是否是真正的 IE7:UA 包含 IE7 時,若是 documentMode 等於 undefined,就必定是真正的 IE7 瀏覽器。對於 IE8+,這種方法就力不從心。例如 IE10 在瀏覽器模式爲 IE8,文本模式爲 IE8標準 時,與真正的 IE8 比較,不管是 UA,仍是 document.documentMode,都如出一轍。函數
綜上,咱們能夠經過檢查 UA 中 Trident 版本和 IE 版本是否匹配,來判斷瀏覽器是否工做在兼容性視圖模式下。結合 document.documentMode,還能夠判斷出用戶是否使用真正的 IE7 瀏覽器。工具
JScript 引擎版本號
JScript 是 IE 的 JS 引擎,IE 提供了一系列 JS 接口來獲取它的 JScript 信息:post
函數 | 返回值 |
---|---|
ScriptEngine() | JS 中固定返回「JScript」 |
ScriptEngineMajorVersion() | 大版本號 |
ScriptEngineMinorVersion() | 小版本號 |
ScriptEngineBuildVersion() | 內部版本號 |
我用這些接口測試了 IE6~10,發現 JScript 的版本號只與瀏覽器有關,與瀏覽器的瀏覽器模式或文檔模式無關。
瀏覽器 | JScript 版本號 |
---|---|
IE6 | 5.6.8827 |
IE7 | 5.7.22145 |
IE8 | 5.8.18702 |
IE9 | 9.0.16434 |
IE10 | 10.0.16521 |
忽略內部版本號,只關注前兩個數字,咱們會發現,從 IE9 把 JS 引擎換成 Chakra 開始,版本號的規律變了。使人欣慰的是,不一樣的 JScript 版本號對應着不一樣版本的瀏覽器,這對判斷出真正的 IE 版本頗有幫助。例如,要識別低於 IE8 的瀏覽器,下面這樣寫就能夠了。
if
(ScriptEngineMinorVersion() != 0 && ScriptEngineMinorVersion < 8) {
//這是 IE8-
}
|
實際上,IE 支持的條件編譯功能中,有個表示 JScript 版本的條件編譯變量,以下(完整的條件編譯變量清單見這裏):
<
script
type
=
"text/javascript"
>
/*@cc_on
alert(@_jscript_version);
@*/
</
script
>
|
這個變量是「major.minor」格式的 JScript 版本號,跟使用 JS 接口獲取到的版本號一致,也只取決於瀏覽器版本,不受瀏覽器模式和文本模式的影響。
文本模式對 JScript 沒影響?
看完上一節,再看我以前寫的這段:文本模式決定:1)排版引擎;2)JS引擎,有明顯的矛盾。難道以前的結論有誤?
實際上,JS 獲取到的 JScript 版本號僅僅表示了當前瀏覽器自帶的 JScript 引擎版本(例如 IE9 始終是 9.0,IE7 始終是 5.7),並不表明任何狀況均可以使用這個版本 JS 引擎的全部功能,頁面使用哪一種版本的 JScript 引擎仍是由頁面的文本模式來決定。
例如,IE8 的 JScript 版本是 5.8,可是隻有在文本模式等於 IE8標準 時纔可使用 JScript5.8 的功能,其它任何文本模式都會致使頁面使用 JScript5.7。
舉個例子,JScript5.8 增長了對 JSON 的支持,因此 IE8 支持原生 JSON 對象。但網上不少人問爲何在 IE8/9 下沒法使用原生 JSON。一種多是頁面沒寫 DTD,致使頁面進入了 IE5怪異 這種文本模式,進而啓用了不支持原生 JSON 的 JScript5.7 致使的。
再舉幾個例子:[,].length 在 JScript9.0 以前是 2;[1,2,3].join(undefined) 在 JScript5.8 以前是"1undefined2undefined3"。把 IE9 的文本模式分別改爲 IE9標準、IE8標準 和 IE7標準,能夠獲得下表:
文本模式 | [,].length | [1,2,3].join(undefined) | 使用的 JScript 版本 |
---|---|---|---|
IE7標準 | 2 | "1undefined2undefined3" | 5.7 |
IE8標準 | 2 | "1,2,3" | 5.8 |
IE9標準 | 1 | "1,2,3" | 9.0 |
相似的例子還有不少。大部分狀況下,頁面使用的 JScript 引擎版本會隨着文本模式的下降而退化,頁面對 JS 的支持度也隨之退化。但教主 franky 提供了一個「for in順序」的反例:
var
o = {1 :
'0'
, 0 :
'1'
};
for
(
var
i
in
o) { console.log(i); }
|
對於 IE9+ 瀏覽器,這行代碼輸出順序始終是 0 1;對於 IE9 如下的瀏覽器,輸出順序都是 1 0,並不受文本模式的影響。關於這一點我沒想到比較好的解釋。
一些 DOM 相關的方法,如 document.querySelectorAll,在文本模式爲 IE7標準、IE5怪異 時不可用;addEventListener 在文本模式爲 IE8標準、IE7標準、IE5怪異 時不可用。這說明 IE 瀏覽器對 DOM 的支持度也會隨着文本模式的下降而退化。
可是一些 BOM 方法,卻跟文本模式無關。例如 IE8 開始支持的 postMessage 和 localStorage,只要瀏覽器是 IE8+,不管什麼文本模式,這兩個功能均可用。IE9+ 支持的 window.performance,在 IE9+ 瀏覽器上,也始終可用,跟當前的文本模式無關。
小結下:隨着文本模式的下降,頁面上實際使用的 JScript 引擎會退化,一些高版本支持的語言特性再也不可用(如 JSON),但 for in 的順序問題彷佛不會退化;DOM 相關功能也有相應的退化;但大部分 BOM 接口卻不會退化(如 localStorage)。
總結
本文討論的內容在各部分都小結過,最後只說一個結論:在解決 JS 兼容性問題時,必定要使用能力檢測和特性檢測。由於不管是從 UA 中獲得的瀏覽器信息,仍是從 JS 接口中獲取到的 JScript 引擎版本,都很是不可靠。例如 UA 中包含 IE7,並不必定不支持 IE9+ 的 window.performace。也多是 IE9 瀏覽器使用了 IE9兼容性視圖,UA 確實會變成 IE7,文本模式爲 IE7標準,但不影響對 window.performace 的支持。
另外,雖然 IE 的瀏覽器模式和文本模式很是複雜,組合起來有幾十種狀況,但大部分狀況只能經過開發者工具來構造。例如 UA 中包含 IE9,實際上使用 JScript5.7 的狀況(瀏覽器模式爲 IE9,文本模式爲 IE7標準),正常狀況下不會出現。
參考:
- How Internet Explorer 8 document mode affects JavaScript
- Same Markup: Explaining "@_jscript_version" and Styling New HTML5 Elements
- Versioning Language Features in JScript
- IE9的特性變化 By Franky
本文連接:https://www.imququ.com/post/browser-mode-and-document-mode-in-ie-2.html