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