)瀏覽器的特徵探測(更新 IE9 的判斷)

來源:互聯網
上載者:User

【2010.04.18 更新】
更加嚴格地區分出了 IE 9,
增強了 Opera 的區分能力,
並將 Chrome 的判別特徵換成了引擎特性 [via],
這樣你就能看出國內哪些瀏覽器是從 Chrome 的核心改過來的了,
大家可以動手試試。 :)

【2010.04.17 更新】
IE 9 在我看來改進非常大:
有我所關心的對 Mutation Events 的支援,
還有事件模型的 W3C 化等等……
本文中我就不多冗述,
有機會再另文探討。
由於在項目中大量使用特徵判斷,
IE 9 在這方面最顯著的變化是:
之前那則“最短的 IE 判斷法”已經失效,
一起被修複的還有一直伴隨 IE 的數組 Bug:
非空數組字面量的最後一個元素缺失的問題(即:[null,]),
因此現如今的最短記錄保持者(6位元組的 !-[1,])也已然失效。(而且不支援 CC 壓縮)
你也不要嘗試使用 addEventListener 方法來判別,
因為 IE 9 已經支援了。(事件的改進非常大,這很好)
所以說 IE 已經越來越靠近標準,
如果在項目中有對 IE 進行特殊處理的代碼,
你可能需要在 IE9下重新檢查一下了。

由於我個人依舊是 XP 的忠實擁躉,
而 XP 又很悲劇地無法安裝 IE 9,
所以一些測試是在 Haitao Jia 同學的協助下完成,
在此表示感謝。
也正因為如此,
我沒有進行覆蓋面太廣的測試。
不過目前所發現的唯一“倖存”下來的 IE 系列 Bug 依舊與剛提到的數組 Bug 有關,
微軟修複了字面量裡的 Bug 卻忘了當字串被 split 成數組後卻濤聲依舊啊。
雖然判斷起來稍微麻煩了點,
但不管怎樣這是我目前發現的僅剩不多地可以用來判斷 IE 全系列的代碼:

!','.split(/,/).length

具體的代碼請拖至文末。

【2010.03.18 更新】
IE 8 也支援 window.DataTransfer 這個拖拽時方法,
因此判斷 gecko 核心的條件有所改動,
你可以在原有判斷條件上排除 IE8 ,
或者選擇 window.mozInnerScreenX 這類由 FF3.6 開始提供的 gecko 特有屬性,
(相對應的擷取縱座標屬性 window.mozInnerScreenX)
還有用以檢測某個節點是否滿足某個選取器規則的方法 node.mozMatchesSelector (很實用)

【2010.01.21 更新】
Google 的 Closure Compile 會將 IE 的判斷代碼“壓縮”成:

!+"\u000b1"

要麼壓縮後替換回 !+"\v1",
要麼換其它更安全的方法來判斷 IE 。

【2010.01.03 發表】
在撰寫此文之前,
陳成告訴我 Nicholas C. Zakas 大師幾天前剛好寫了一篇名為
《特徵探測並非瀏覽器探測 (Feature detection is not browser detection) 》
的文章。
文章裡“深刻”批判了 MooTools 所使用的特徵探測法,
但真正令人信服的理由似乎在文中也並無體現,
只是說 MooTools 因 Firefox 3.6 的變化而被迫發布了一次升級,
然後說:

“當瀏覽器(功能)愈發地接近彼此,想從“特徵”去區別它們將變得越來越困難和危險。
(As browsers grow closer together, looking at “features” to separate them will become more difficult and risky.)”

當然啦,
不僅是 Javascript ,
服務端想要統計用戶端也必須依靠 User-Agent  (以下簡稱 UA),
而對於 UA Spoofs ,
尼古拉斯的看法是:

“你必須永遠尊重瀏覽器所告知你的 UA 。
(You should always honor exactly what the browser is reporting as a user-agent.)”

因此從前後端統一的角度,
我個人還是贊同這一觀點的。

但從另一方面看,
現在瀏覽器核心雖稍顯得固定,
但整合多種核心出來闖蕩江湖的瀏覽器也不少,
而且它們在中國的佔有率都不是一般的高,
(但它們對 UA 的管理則不是一般的糟糕)
我想這是尼大師所沒有料到的。
(值得一提的是馬桶 3 的 web-kit 模式這次提供了 UA 特徵符)

因此我覺得對於特徵探測不可一棒子敲死,
而對於 UA 嗅探法也不能一味地捧上天,
能夠準確判斷出瀏覽器繼而進行正確的 Hack 來確保完整體驗才是王道。

呃……
寫了這麼多,
完全是針對尼大師的新文有感而發,
我預想中的本文從這裡開始——

由於 Firefox 3.6 產生了巨大的變化,
(當然不僅是 Javascript 這個層面,
也比如舊的 chrome 註冊檔案 contents.rdf 也被廢止等等)
我們理應將 3.6 版本作為 Firefox 的一個裡程碑版本來對待。
對於本文而言,
也就是傳說中用來區別 Firefox 的諸多特徵已經消失:
比如最令人熟知的 window.getBoxObjectFor() ,
再比如 /a/[-1] == 'a' 這個 trick 。
因此我們必須找一個新的特徵來填上這個漏洞,
(想從 Firefox 1.0 找一個延續至今的特徵極為困難)
查閱文檔後你剛好可以找到一個從 3.6 開始
被 Firefox 用來儲存拖拽時資料的方法 window.DataTransfer() , (經查 IE8 同樣支援)
被 Firefox 提供用以擷取可視地區相對視窗橫/縱座標的屬性 window.mozInnerScreenX/Y ,
而且經測試在最新的 Firefox 3.7a1pre nightly 也得到支援。

因此經過整理匯總,
我個人比較贊同的特徵探測方法如下:

(function (win, doc) {
    var isIE = !','.split(/,/).length,
        isIE6 = isIE && !win.XMLHttpRequest,
        isIE8 = !!win.XDomainRequest,
        isIE9 = isIE && !!+'\v1',                                 // alt: !!-[1,]
        isIE7 = isIE && !isIE6 && !isIE8 && !isIE9,
        isFF = !!doc.getBoxObjectFor || 'mozInnerScreenX' in win, // gecko
        isOP = !!win.opera && !!win.opera.toString().indexOf('Opera'),
        isOP9 = /^function \(/.test([].sort),
        isWK = !!win.devicePixelRatio,                            // web-kit
        isSF = /a/.__proto__ == '//',                             // safari
        isCR = /s/.test(/a/.toString);                            // chrome
})(window, document);

其中值得一提的是 web-kit 核心,
window.devicePixelRatio() 能區分出所有的 web-kit based 瀏覽器,
其中包括 Maxthon 3 的極速模式和其它尚未發布的類似瀏覽器。
Chrome 比 Safari 多一個 window.MessageEvent,
但要注意排除 Firefox。

最後呢,
我還整理了 Firefox 重大裡程碑版本的特徵判斷法,
不建議被納入通用的判斷方法裡,
但是如果你剛好被這些版本的差異所困擾時,
它們應該能有用:

(function (win) {
    var aboveFF36 = 'mozInnerScreenX' in win,      // alt: !!document.body.mozMatchesSelector
        aboveFF35 = !!Object.getPrototypeOf,
        aboveFF2 = !!win.globalStorage;
        aboveFF3 = upperFF2 && !!win.MessageEvent, // alt: 'reduce' in Array
        aboveFF15 = 'some' in Array;
})(window);

其中 3.0 和 3.6 是我個人覺得變化最大的兩個裡程碑版本,
指不定什麼時候你就能用到。
另外,
Firefox 的重大版本變化幾乎總跟隨著 Javascript 的版本升級,
因此對於 3.0 版本你還可以用 'reduce' in Array 來判斷,
當然前提是你沒有對 Array 進行擴充。

Ref:
《Javascript瀏覽器判斷終極技巧》
《JavaScript 判斷瀏覽器類型及版本》
(以上兩文總結得都很不錯,
 只是 Firefox 和 Safari 的部分需要更新)
《Detecting browsers javascript hacks》 (推薦)

寫得很亂很雜,
這次就不照例了……

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.