IE 的瀏覽器模式和文字模式(二)
提醒:本文最後更新於 1952 天前,文中所描述的資訊可能已發生改變,請謹慎使用。
一年半之前我寫了一篇《關於瀏覽器模式和文字模式的困惑》,介紹了 IE8+ 特有的瀏覽器模式(Browser Mode)和文字模式(Document Mode),以及我的測試和微軟文件有出入的部分。其中有一些沒有提到的內容,本文繼續討論。
判斷真正的 IE 版本
很多 JS 框架都通過 UA 判斷 IE 的版本。對於 IE6,這種做法沒問題( IE6 沒有瀏覽器模式的概念,也沒有其它 IE 可以把瀏覽器模式改為 IE6;IE7 雖然也沒有瀏覽器模式,但 IE8+ 可以把瀏覽器模式設定為 IE7 模式)。但是從 IE8 開始引入的瀏覽器模式會產生不同的 UA。例如,IE9 有這些:
瀏覽器模式 | navigator.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 三種不同結果。
實際上,對於 IE8+,根據 UA 字串只能確定當前是否是相容性檢視。因為相容性檢視的 UA 中,IE 版本和 Trident 版本不匹配。例如 UA 裡同時有「MSIE 7.0」和「Trident/6.0」,說明瀏覽器模式肯定是 IE10相容性
除此之外,上面 IE7 和 IE8 這兩種瀏覽器模式,UA 和跟真正的 IE7 或 IE8 沒有任何區別,根據 UA 完全沒辦法區分。甚至連 IE9 模式,我們也無法確認這是 IE9 瀏覽器的預設模式,還是 IE10 瀏覽器的 IE9 模式。
下面來看看文字模式,依然用 IE9 測試。選擇不同的文字模式,documentMode 的值也不一樣。
文字模式 | 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 資訊:
函式 | 返回值 |
---|---|
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 版本的條件編譯變數,如下(完整的條件編譯變數清單見這裡.aspx)):
<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標準),正常情況下不會出現。
參考:
--EOF--
發表於 2013-09-07 02:50:37 ,並被新增「 IE 」標籤 。檢視本文 Markdown 版本 »
提醒:本文最後更新於 1952 天前,文中所描述的資訊可能已發生改變,請謹慎使用。
相關推薦
IE 的瀏覽器模式和文字模式(二)
提醒:本文最後更新於 1952 天前,文中所描述的資訊可能已發生改變,請謹慎使用。 一年半之前我寫了一篇《關於瀏覽器模式和文字模式的困惑》,介紹了 IE8+ 特有的瀏覽器模式(Browser Mode)和文字模式(Document Mode),以及我的測試和微軟文件有出入的部分。其中有一些沒有提
關於瀏覽器模式和文字模式的困惑
提醒:本文最後更新於 2528 天前,文中所描述的資訊可能已發生改變,請謹慎使用。 什麼是瀏覽器模式和文字模式? 經常使用IE開發者工具的同學,肯定見過瀏覽器模式和文字模式,對於這兩個名詞,綜合相關文件解釋如下: 瀏覽器模式(Browser Mode),用於切換IE針對該網頁的預設文字模式、對不
設計模式之設計原則(二)
font 通過 size 模式 span 通信 轉發 設計模式 其他 五: 接口分離原則:不應該強迫程序依賴它們不需要使用的方法。即,一個接口不需要提供太多的行為,一個接口應該只提供一種對外的功能,不應該把所有的操作都封裝到一個接口中。 六: 迪米特原則:一個對象應
哈爾濱工業大學計算機學院-模式識別-課程總結(二)-概率密度函式的引數估計
1. 概率密度函式的引數估計 前文講到了利用貝葉斯決策理論構建貝葉斯分類器,初學者難免會有疑問,既然已經可以通過構建貝葉斯分類器的方法處理分類問題,那為什麼還要學習本章節內容? 事實上,貝葉斯分類器的缺可以通過計算先驗概率與類條件概率來設計最優分類器。但是對於大多數實際問題,我們往往無法知道這兩個
哈爾濱工業大學計算機學院-模式識別-課程總結(二)-概率密度函數的參數估計
展開 處理 play bold 避免 dot max 應用 既然 1. 概率密度函數的參數估計 前文講到了利用貝葉斯決策理論構建貝葉斯分類器,初學者難免會有疑問,既然已經可以通過構建貝葉斯分類器的方法處理分類問題,那為什麽還要學習本章節內容? 事實上,貝葉斯分類器的缺可以
設計模式簡單小例子(二)結構型模式
簡單小例子 原始碼已經上傳到了GitHub. https://github.com/tanglonghui/DesignPatterns 設計模式簡單小例子(一) 建立型模式: https://blog.csdn.net/qq_40687864/article/details/810
從零開始構建一個Reactor模式的網路庫(二)執行緒類Thread
執行緒類Thread是對POSIX執行緒的封裝類,因為要構建的是一個Linux環境下的多執行緒網路庫,對執行緒的封裝是很必要的。 首先是CurrentThread名稱空間,主要是獲取以及快取執行緒id: 1 #ifndef CURRENTTHREAD_H 2 #define CURRENTTHR
《設計模式——java版》(二)
第三章 建立型模式簡介 一、單例模式 1. 意思是:確保一個類只有一個例項,而且自行例項化並向整個系統提供這個例項 2. 適
RabbitMQ入門及常用的5種模式的簡單使用(二)
RabbitMQ是一個非常常用也非常強大的訊息中介軟體,主要用於應用與應用之間的通訊,有五種常見的使用方式,分別是:簡單模式,工作模式,釋出訂閱模式,路由模式以及萬用字元模式,這裡主要是路由模式的三種具
Activity的啟動模式和任務棧(4)
我們在開發專案的過程中,會涉及到該應用中多個Activity元件之間的跳轉,或者夾帶其它應用的可複用的Activity。例如我們可能希望跳轉到原來某個Activity例項,而不是產生大量重複的 Activity。這樣就需要我們為 Activity 配置特定的載入模式,而不是使用預設的載入模式。 Ac
設計模式六大原則例子(二)-- 單一職責原則(SRP)例子
之前我們對設計模式的六大原則做了簡單歸納,這篇部落格是對單一職責原則進行的舉例說明。 單一職責原則的意義 物件不應該承擔太多職責,正如人不應該一心分為二用。唯有專注,才能保證物件的高內聚;唯有單一,才能保證物件的細粒度。物件的高內聚與細粒度有利於物件的
命令和符號總結(二)
命令2017-05-13隨記—————————————————————————————— 20.uname 顯示系統內核信息 -r 顯示內核版本 -m 32位,64位本文出自 “一個Linux小白-學習運維” 博客,謝絕轉載!命令和符號總結(二)
SpringMVC中文件的上傳(上傳到服務器)和下載問題(二)--------下載
cat exc stream log trac close pri page fin 一、建立一個簡單的jsp頁面。 我們在建好的jsp的頁面中加入一個超鏈接:<a href="${pageContext.request.contextPath}/down
Java數據結構和算法(二)——數組
image 創建 函數 編程 局限性 總結 遍歷數組 ron 添加 上篇博客我們簡單介紹了數據結構和算法的概念,對此模糊很正常,後面會慢慢通過具體的實例來介紹。本篇博客我們介紹數據結構的鼻祖——數組,可以說數組幾乎能表示一切的數據結構,在每一門編
Spring整合Struts2和Hibernate+Maven(二)之SSH的配置檔案
上次講到的是maven專案的建立以及pom.xml的配置。 這裡推薦一個網站:maven整合jar包,這裡可以查詢並生成配置檔案中jar包匯入格式的文字,複製貼上到pom.xml中即可由idea自動下載並匯入專案。 resources資料夾 建立ssh的配置檔案至上章圖片中的res
資料結構和演算法緒論(二)
1、演算法概念 不同的演算法可以提高計算相同算術題的效率,那麼演算法的研究就變得有意義了。 2、演算法的特性 輸入 輸出 有窮性(執行有限的步驟) 確定性(每一個步驟僅有一個含義) 可行性 3、演算法設計要求 沒有無法錯誤、有合法輸入和輸出 4、演算法效率 度量方法: 事前分析估算方法
Java抽象類和接口(二)
system args 程序 包含 多重 代碼 apt r.java 可擴展 ***************************接口********************************* 一.why 需求一直不變的時候可以不使用接口, 需求經常發生改變推薦使
OSI模型中物理層的通訊形式總結之模擬傳輸和數字傳輸(二)
模擬傳輸與數字傳輸[檢視定義] 1.模擬傳輸系統 背景 儘管模擬傳輸劣於數字傳輸(傳輸過程中,模擬傳輸容易受干擾,訊號易衰減,安全性也不高),但由於採用模擬傳輸技術的電話網在計算機網路出現以前就已運行了近一個世紀,因此世界各地幾乎都有這種電話網,雖然數字傳輸和數字網是今後網路
Android之測量APP效能-分析和除錯 APK(二)
分析和除錯預構建 APK Android Studio 3.0 允許您分析和除錯 APK,無需先從 Android Studio 專案構建這些 APK。 不過,您需要確保使用可除錯版本的 APK。 要開始除錯 APK,請在 Android Studio Welcome 歡迎螢幕中點選&nbs
【筆記】ARM架構和ARM晶片(二)
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!