《JavaScript高級(jí)程序設(shè)計(jì)》Chapter 9 客戶端檢測

Chapter 9 客戶端檢測

能力檢測

  1. 用于識(shí)別瀏覽器的能力,基本模式如下

    if (object.propertyInQuestion) {
        // use object.propertyInQuestion
    }
    
    function getElement(id) {
        if (document.getElementById) {
            return document.getElementById(id);
        } else if (document.all) {
            return document.all[id];
        } else {
            throw new Error('No way to retrieve element');
        }
    }
    
  2. 更可靠的能力檢測

    • 確定一個(gè)對象是否支持排序(既要檢測 sort 屬性是否存在察净,也要檢測 sort 屬性是否是一個(gè)函數(shù))
    function isSortable(object) {
        return typeof object.sort == 'function';
    }
    
    • 盡量使用 typeof 進(jìn)行能力檢測嗜价。但是在 IE8 之前的版本中迈勋,由于宿主對象是通過 COM 而非 JScript 實(shí)現(xiàn)的烫堤,所以 document.createElement() 之類的函數(shù)是一個(gè) COM 對象陪汽,而非函數(shù)
    typeof document.createElement == 'function' // 在 IE8- 中為 false
    
    • IE 中類似的 typeof 的行為不標(biāo)準(zhǔn)的例子還有很多悄晃。
    • 在瀏覽器環(huán)境下測試任何對象的某個(gè)屬性是否存在玫霎,要使用下面這個(gè)函數(shù)
    function isHostMethod(object, property) {
        var t = typeof object[property];
        return t == 'function' || (!!(t == 'object' && object[property])) || t == 'unknown;
    
    result = isHostMethod(xhr, 'open'); // true
    

    在 JavaScript 中, !! 操作符通常用于將表達(dá)式強(qiáng)制轉(zhuǎn)換為 boolean 類型數(shù)據(jù)妈橄。

  3. 能力檢測庶近,不是瀏覽器檢測

    • 檢測某個(gè)或某幾個(gè)特性并不能夠確定瀏覽器。
    • 如果已知應(yīng)用程序需要使用某些特定的瀏覽器特性眷蚓,最好一次檢測所有的相關(guān)特性鼻种,而不是分別檢測。
    // 檢測瀏覽器是否具有 DOM1 級(jí)規(guī)定的能力沙热。
    var hasDOM1 = !! (document.getElementById && document.createElement && document.getElementByTagName);
    

怪癖檢測

  1. 怪癖檢測的目標(biāo)是識(shí)別瀏覽器的特殊行為叉钥。通過怪癖檢測罢缸,獲知瀏覽器存在什么樣的缺陷。

  2. Example: IE8- 中投队,如果某個(gè)實(shí)例屬性與 [[Enumerable]] 標(biāo)記為 false 的某個(gè)原型屬性同名瓷产,那么該實(shí)例屬性將不會(huì)出現(xiàn)在 for-in 循環(huán)當(dāng)中矗蕊。

    var hasDontEnumQuirk = function() {
        var o = {toString: function() {
            for(var prop in o) {
                if(prop == 'toString') {
                    return false;
                }
            }
        }
        return true;
    }();
    
  3. Example: Safari3- 中,會(huì)枚舉被隱藏的屬性。

var hasEnumShadowsQuirk() {
    var o = {toString: function() {
        var count = 0;
        for (var prop in o) {
            if (prop == 'toString') {
                count++;
            }
        }
        return (count > 1);
    }();
3. Example: Safari3- 中神得,會(huì)枚舉被隱藏的屬性。

```
var hasEnumShadowsQuirk() {
    var o = {toString: function() {
        var count = 0;
        for (var prop in o) {
            if (prop == 'toString') {
                count++;
            }
        }
        return (count > 1);
    }();
```

用戶代理檢測

  1. 用戶代理檢測通過檢測用戶代理字符串來確定實(shí)際使用的瀏覽器败富。在每一次 HTTP 請求過程中舟山,用戶代理字符串是作為相應(yīng)首部發(fā)送的,而且該字符串可以通過 JavaScript 的 navigator.userAgent 屬性訪問谎碍。

    • 在服務(wù)器端鳞滨,用戶代理檢測被廣泛使用。
    • 在客戶端蟆淀,用戶代理檢測的優(yōu)先級(jí)排在能力檢測 / 怪癖檢測之后拯啦。
  2. 電子欺騙:瀏覽器通過在自己的用戶代理字符串加入一些錯(cuò)誤或誤導(dǎo)信息,來達(dá)到欺騙服務(wù)器的目的熔任。

  3. 用戶代理字符串

    • RFC2616 規(guī)定格式:標(biāo)識(shí)符/產(chǎn)品版本號(hào)
    • IE4 ~ IE7:Mozilla/4.0 (平臺(tái); MSIE 版本號(hào); 操作系統(tǒng))
    • IE8:Mozilla/4.0 (compatible; MSIE 版本號(hào); Trident/Trident 版本號(hào))
      • Trident 記號(hào)是為了讓開發(fā)人員知道 IE8 是不是在兼容模式下運(yùn)行褒链,如果是,則 MSIE 版本號(hào)會(huì)變成 7疑苔。
    • IE9:Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)
    • IE9 兼容模式:Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/5.0)
    • Gecko:Mozilla/Mozilla 版本號(hào) (平臺(tái); 加密類型; 操作系統(tǒng)或CPU; 語言; 預(yù)先發(fā)型版本) Gecko/Gecko 版本號(hào) 應(yīng)用程序或產(chǎn)品/引用程序或產(chǎn)品版本號(hào)
      • 具體查手冊
    • Firefox4: Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox 4.0.1
    • Webkit:Mozilla/5.0 (平臺(tái); 加密類型; 操作系統(tǒng)或CPU; 語言) AppleWebkit/AppleWebkit 版本號(hào) (KHTML, like Gecko) Safari/Safari 版本號(hào)
      • 基于 Webkit 的所有瀏覽器都將自己標(biāo)識(shí)為 Mozilla 5.0
    • Safari3:Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebkit/522.15.5 (KHTML, like Gecko) Version/3.0.3 Safari/522.15.5
    • Konqueror 略
    • Chrome7:Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebkit/534.7 (KHTML, like Gecko) Chrome/7.0.517.44 Safari/534.7
    • Opera8:Opera/版本號(hào) (操作系統(tǒng)或CPU; 加密類型; 語言)
    • Opera9:Mozilla/5.0 (Windows NT 5.1; U; en-US; rv:1.8.1) Gecko/20061208 Firefox/2.0.0 Opera 9.50
      • Opera隱藏了自己的身份甫匹,偽裝成 Firefox 或 IE,無法將 Opera 與其他瀏覽器區(qū)別開來惦费。
    • Opera10:Opera/9.80 (操作系統(tǒng)或CPU; 加密類型; 語言) Presto/Presto 版本號(hào) Version/版本號(hào)
    • iOS 和 Android:同桌面版
  4. 用戶代理字符串檢測技術(shù)

    • 識(shí)別呈現(xiàn)引擎

      • 檢測五大引擎:IE兵迅、Gecko、WebKit薪贫、KHTML恍箭、Opera
      • 使用模塊增強(qiáng)模式封裝檢測腳本
      var client = function() {
          var engine = {
              ie: 0,
              gecko: 0,
              webkit: 0,
              khtml: 0,
              opera: 0,
              
              ver: null
          };
          
          return {
              engine: engine
          };
      }();
      
      • 如果檢測到了哪個(gè)呈現(xiàn)引擎,就以浮點(diǎn)數(shù)值形式將該引擎的版本號(hào)寫入相應(yīng)的屬性瞧省。而呈現(xiàn)引擎的完整版本(是一個(gè)字符串)扯夭,則被寫入 ver 屬性。
      if(client.engine.ie) {
          // 針對 IE 的代碼
      } else if (client.engine.gecko > 1.5) {
          if (client.engine.ver == '1.8.1') {
              // 針對這個(gè)版本執(zhí)行某些代碼
          }
      }
      
      • 識(shí)別 Opera 必須檢測 window.opera 對象鞍匾。
      if (window.opera) {
          engine.var = window.opera.version();
          engine.opera = parseFloat(engine.ver);
      
      • 識(shí)別 WebKit 和 KHTML 見手冊勉抓。
    • 識(shí)別瀏覽器(具體見文檔)

    var browser = {
        ie: 0,
        firefox: 0,
        safari: 0,
        konq: 0,
        opera: 0,
        chrome: 0,
        ver: null
    };
    
    • 識(shí)別平臺(tái)(具體見文檔)
    var system = {
        win: false,
        mac: false,
        x11: false
    };
    var p = navigator.platform;
    system.win = p.indexOf('Win') == 0;
    system.mac = p.indexOf('Mac') == 0;
    system.x11 = (p.indexOf('X11') == 0) || (p.indexOf('Linux') == 0); 
    
    • 識(shí)別移動(dòng)設(shè)備(具體見文檔)
    var system = {
        win: false,
        mac: false,
        x11: false,
        
        iphone: false,
        ipod: false,
        ipad: false,
        ios: false,
        android: false,
        nokiaN: false,
        winMobile: false
    };
    var p = navigator.platform;
    system.win = p.indexOf('Win') == 0;
    system.mac = p.indexOf('Mac') == 0;
    system.x11 = (p.indexOf('X11') == 0) || (p.indexOf('Linux') == 0); 
    
    system.iphone = ua.indexOf('iPhone') > -1;
    system.ipod = ua.indexOf('iPod') > -1;
    system.ipad = ua.indexOf('iPad') > -1;
    system.nokiaN = ua.indexOf('NokiaN') > -1;
    system.winMobile = (system.win == 'CE');
    
    • 識(shí)別游戲系統(tǒng)(略)
  5. 完整的代碼(看文檔)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市候学,隨后出現(xiàn)的幾起案子藕筋,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件隐圾,死亡現(xiàn)場離奇詭異伍掀,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)暇藏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進(jìn)店門蜜笤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人盐碱,你說我怎么就攤上這事把兔。” “怎么了瓮顽?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵县好,是天一觀的道長。 經(jīng)常有香客問我暖混,道長缕贡,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任拣播,我火速辦了婚禮晾咪,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘贮配。我一直安慰自己谍倦,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布泪勒。 她就那樣靜靜地躺著剂跟,像睡著了一般。 火紅的嫁衣襯著肌膚如雪酣藻。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天鳍置,我揣著相機(jī)與錄音辽剧,去河邊找鬼。 笑死税产,一個(gè)胖子當(dāng)著我的面吹牛怕轿,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播辟拷,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼撞羽,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了衫冻?” 一聲冷哼從身側(cè)響起诀紊,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎隅俘,沒想到半個(gè)月后邻奠,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體笤喳,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年碌宴,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了杀狡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,137評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡贰镣,死狀恐怖呜象,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情碑隆,我是刑警寧澤恭陡,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站干跛,受9級(jí)特大地震影響子姜,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜楼入,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一哥捕、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧嘉熊,春花似錦遥赚、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至孕惜,卻和暖如春愧薛,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背衫画。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工毫炉, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人削罩。 一個(gè)月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓瞄勾,卻偏偏與公主長得像,于是被迫代替她去往敵國和親弥激。 傳聞我的和親對象是個(gè)殘疾皇子进陡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內(nèi)容