第3章 瀏覽器
每種瀏覽器都包含一個代碼引擎或渲染引擎,它負(fù)責(zé)解釋W(xué)eb頁面上的代碼,javascript解釋器是其中的一部分。
Netscape4慘敗之后,網(wǎng)景公司于1998年創(chuàng)立了Mozilla項目,開發(fā)了Gecko引擎,現(xiàn)在它支持著Mozilla, Firefox, Netscape, Camino等瀏覽器。
Explorer的代碼引擎叫做Trident,1999年3月發(fā)布的Explorer5.0是第一個支持W3C DOM和XMLHttpRequest的瀏覽器,但也是最后一個包含了主要Javascript更新的Explorer版本。
Safari于2003年發(fā)布,它使用KHTML代碼引擎,它是Macintosh平臺的默認(rèn)瀏覽器。
Opera是一個獨(dú)立的瀏覽器,在瀏覽器大戰(zhàn)期間,它沒有實現(xiàn)DHTML,現(xiàn)在看來,這是一個相當(dāng)英明的決定。
4種兼容性問題
不支持:這些出現(xiàn)問題的功能不是“不可或缺”的基礎(chǔ)功能,都能夠通過對象檢測判斷,而且瀏覽器也在努力消除這些問題,如document.sytleSheets來讀寫整個樣式表,目前Safari和Opera也增加了對其的支持。
合理的不同看法:如defer屬性對加載腳本的要求,Exploer有獨(dú)特的理解,幸好這種問題是最少有的。
有意為之的兼容性問題:通常是瀏覽器大戰(zhàn)的遺留問題,也可以通過對象檢測來判斷,一旦微軟著手實現(xiàn)W3C事件標(biāo)準(zhǔn),最后一批被故意造成的兼容性問題也將得到解決。
瀏覽器bug:這是由于編程的缺陷造成的不可預(yù)見的錯誤,它是無法解決也是無法衡量的。如Exploer6會被normalize()方法導(dǎo)致崩潰。
瀏覽器兼容性問題是單純的生活的事實,它不會輕易消失,應(yīng)該盡快地習(xí)慣它,至少聽任它。
在任何情況下都不要先為某一個瀏覽器寫腳本,然后增加其他瀏覽器的支持。在項目支出就應(yīng)該解決這些兼容性問題,而不是放在最后。
對象檢測
對象檢測是避免兼容性問題的最佳助手。它的一般方法是檢查想使用的對象,看它們是否存在,如果不存在,就結(jié)束函數(shù)。(if(!對象)),從技術(shù)上說,對象檢測是把一個對象轉(zhuǎn)換成一個布爾值。
檢查W3C DOM:
var W3CDOM = document.createElement && document.getElementsByTagName;
對W3C DOM的檢測使我們可以總是假設(shè)瀏覽器也支持相關(guān)的功能,如appendChild,而省去對它的檢查。
事件處理測試:
function addEventSimple(obj, evt, fn) {
if (obj.addEventListener) //W3C
obj.addEventListener(evt, fn, false);
else if (obj.attachEvent) //微軟
obj.attachEvent('on' + evt, fn);
}
我們期望未來的版本使用標(biāo)準(zhǔn),所以對標(biāo)準(zhǔn)的支持應(yīng)該最先檢查,事實上先檢查attachEvent,F(xiàn)x等瀏覽器會報錯。
瀏覽器檢測
為什么瀏覽器檢測行不通?瀏覽器兼容性模式是不斷變化的,今天不支持的屬性,明天可能會支持;而且瀏覽器常常會偽裝自己的身份,以便通過瀏覽器檢測。
瀏覽器檢測的軍備競賽
navigator.userAgent中保存了每一個瀏覽器的識別字符串。1995年前后的Mosaic和Netscape年代中,由于
Netscape的cookie和<center>標(biāo)簽等的支持,服務(wù)器端的程序員決定使用瀏覽器檢測來區(qū)分兩種瀏覽器,他們檢測識別字符串
是否從Mozilla/開始,這給javascript世界帶來了不必要的磨難。瀏覽器廠商被迫將自己的識別字符串變成從Mozilla/開始,即便是
Explorer最初進(jìn)入市場時也將自己偽裝成了Netscape。瀏覽器大戰(zhàn)開始后,Web開發(fā)者們做出反應(yīng),他們創(chuàng)建了更多的瀏覽器程序來區(qū)分
Netscape和Exploer,而當(dāng)戰(zhàn)爭結(jié)束時,已經(jīng)有數(shù)不清的網(wǎng)站設(shè)置了檢測腳本只允許Explorer訪問,歷史重演了,一些瀏覽器如
Opera,又不得不修改自己的識別字符串來匹配Explorer,甚至將識別字符串的設(shè)置開放給用戶。
拆解瀏覽器字符串
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.12) Gecko/20050915
Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)
Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/312.8 (KHTML, like Gecko) Safari/312.6
Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2)
第一個是Mozilla1.7.12,第二個是NT5.1(即XP)的Explorer6.0,第三個是Safari1.3.2,第四個是偽裝后的Safari1.3.2。
userAgent:使用navigator.userAgent,而不是navigator.appName和navigator.appVersion。前者尚有一些遵循,后者都是謊言;
Mozilla/:只能證明瀏覽器是1994年后發(fā)布的;
/[version number]:沒有意義,每一個現(xiàn)代瀏覽器都生命是第4版或第5版的Mozilla;
不規(guī)則字符串:通常被圓括號包圍,包含這非常復(fù)雜的縮寫;
Opera:唯一支持window.opera屬性,可以檢測這個對象來判斷;
Safari, iCab和Konqueror:不像Opera那樣勇于承擔(dān)風(fēng)險,它們可以完全地偽裝自己;
Gecko:Mozilla識別串通常都會包含Gecko,但不幸Safari等也包含;
MSIE:沒有意義,絕大多數(shù)的瀏覽器都包含MSIE;
版本號:Exploer和Opera允許在名字后面找到自己的版本號,而其他瀏覽器都無效,比如Mozilla的隱藏版本;
操作系統(tǒng):Windows操作系統(tǒng)都以Win開始,當(dāng)然這不適用于偽裝的串。
(http://www.quirksmode.org/js/detect.html)
瀏覽器檢測的正確使用
當(dāng)你需要知道訪問者的瀏覽器,如站點統(tǒng)計時,這些檢測不會影響腳本邏輯。
當(dāng)我們用對象檢測時需要排除瀏覽器bug等時,可以將對象檢測和瀏覽器檢測一起使用。
調(diào)試
Mozilla有最好的錯誤信息,因此多在Mozilla中調(diào)試;
使用return,alert,confirm是不錯的方法,復(fù)雜的調(diào)試可以自己創(chuàng)建一個錯誤控制臺;
將bug報告給瀏覽器廠商。