document.getElementById()
這個DOM方法,儘管可使用非標準的document.all
屬性實現相同的目的。因而就有相似下面的能力檢測代碼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!"); } }
function getWindowWidth() { if (document.all) { // 假設這裏是IE瀏覽器 return document.documentElement.clientWidth; // 錯誤的用法 } else { return window.innerWidth; } }
// 這不是能力檢測——只是檢測了是否存在相應的方法 function isSortable(object) { return !!object.sort; } // 任何包含sort屬性的對象都會返回true var result = isSortable({sort: true});
// 這樣更好:檢測sort是否是函數 function isSortable(object) { return typeof object.sort == "function"; }
typeof
操做符進行能力檢測。特別是,宿主對象沒有義務讓typeof
返回合理的值。最使人髮指的事就發生在 IE 中。大多數瀏覽器在檢測到document.createElement()
存在時,都會返回true// 在IE8及以前版本不行 function hasCreateElement() { return typeof document.createElement == "function"; }
typeof document.createElement
返回的的是「object」,而不是「function」。如前所述,DOM對象是宿主對象,IE及更早版本中的宿主對象是經過COM而非JScript實現的。所以,document.createElement()
函數確實是一個COM對象。IE9糾正了這個問題,對全部DOM方法都返回"function"。// 還不夠具體 var isFirefox = !!(navigator.vendor && navigator.vendorSub); // 假設過頭了 var isIE = !!(document.all && document.uniqueID);
navigator.vendor
和navigator.vendorSub
確實是Firefox的獨有屬性,可是後來Safari也依樣畫葫蘆實現了相同的屬性。document.all && document.uniqueID
這兩個屬性是早期IE的獨有屬性,目前還存在,但不保證將來IE不會去掉。// 肯定瀏覽器是否支持 Netscape風格的插件 var hasNSPlugins = !!(navigator.plugins && navigator.plugins.length); // 肯定瀏覽器是否具備DOM1級規定的能力 var hasDOM1 = !!(document.getElementById && document.createElement && document.getElementsByTagName);
for-in
循環中。// 檢測上述怪癖的代碼 var hasDontEnumQuirk = function() { var o = { toString: function() {} }; for (var prop in o) { if (prop == "toString") { return false; } } return true; }
var hasEnumShadowsQuirk = function() { var o = { toString: function() {} }; var count = 0; for (var prop in o) { if (prop == "toString") { count++; } } // 若是瀏覽器存在這個bug // 就會返回兩個 toString 的實例 return (count > 1); }
navigator.userAgent
屬性訪問。略javascript
var client = function() { var engine = { // 呈現引擎 ie: 0, gecko: 0, webkit: 0, khtml: 0, opera: 0, // 具體的版本號 ver: null }; // 在此檢測呈現引擎、平臺和設備 ... return { engine: engine }; }();
if (client.engine.ie) { // 若是是IE client.ie 應該大於0 ... } else if (client.engine.gecko > 1.5) { if (client.engine.ver === "1.8.1") { // 針對這個版本的操做 ... } }
window.opera
對象。Opera5+都有這個版本。在Opera7.6+中調用version()
方法能夠返回一個表示瀏覽器版本的字符串。if (window.opera) { engine.ver = window.opera.version(); engine.opera = parseFloat(engine.ver); }
Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36
\S
。用戶代理字符串中的版本號與下一部分的分隔是一個空格,所以這個模式能夠保證捕獲全部版本信息。var ua = navigator.userAgent; if (/AppleWebKit\/(\S+)/.test(ua)) { // \S 表示非空格的特殊字符 // \S+ 表示不包含空格的子字符串 // 小括號表示將此子字符串加入捕獲組 // RegExp["$1"] 表示捕獲組的第一個元素,即爲上面描述的子字符串 engine.ver = RegExp["$1"]; engine.webkit = parseFloat(engine.ver); }
if (/KHTML\/(\S+)/.test(ua) || /Konqueror\/([^;]+)/.test(ua)) { engine.ver = RegExp["$1"]; engine.khtml = parseFloat(engine.ver); }
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.11) Gecko/20071127 Firefox/2.0.0.11
// 在上面的字符串中實際匹配的是"rv:1.8.1.11) Gecko/20071127" // gecko的版本號位於 rv: 與一個閉括號之間,所以爲了提取出這個版本號 // [^\)]+ 就是將 rv: 以後的字符串排除 ) 閉括號 以後加入捕獲組 // 正則表達式要查找全部不是閉括號的字符,還要查找字符串"Gecko/"後跟8個數字 if (/rv:([^\)]+)\) Gecko\/\d{8}/.test(ua)) { engine.ver = RegExp["$1"]; engine.gecko = parseFloat(engine.ver); }
// 五個呈現引擎完整的檢測代碼以下 var ua = navigator.userAgent; if (window.opera) { engine.ver = window.opera.version(); engine.opera = parseFloat(engine.ver); } else if (/AppleWebKit\/(\S+)/.test(ua)) { engine.ver = RegExp["$1"]; engine.webkit = parseFloat(engine.ver); } else if (/KHTML\/(\S+)/.test(ua) || /Konqueror\/([^;]+)/.test(ua)) { engine.ver = RegExp["$1"]; engine.khtml = parseFloat(engine.ver); } else if (/rv:([^\)]+)\) Gecko\/\d{8}/.test(ua)) { engine.ver = RegExp["$1"]; engine.gecko = parseFloat(engine.ver); } else if (/MSIE ([^;]+)/.test(ua)) { engine.ver = RegExp["$1"]; engine.ie = parseFloat(engine.ver); }
// 咱們的檢測代碼須要添加瀏覽器的檢測 var client = function() { var engine = { // 呈現引擎 ie: 0, gecko: 0, webkit: 0, khtml: 0, opera: 0, // 具體的版本號 ver: null }; var browser = { // 瀏覽器 ie: 0, firefox: 0, safari: 0, konq: 0, opera: 0, chrome: 0, // 具體的版本號 ver: null } // 在此檢測呈現引擎、平臺和設備 ... return { engine: engine, browser: browser }; }();
var ua = navigator.userAgent; if (window.opera) { engine.ver = browser.ver = window.opera.version(); engine.opera = browser.opera = parseFloat(engine.ver); } else if (/AppleWebKit\/(\S+)/.test(ua)) { engine.ver = RegExp["$1"]; engine.webkit = parseFloat(engine.ver); // 肯定是Chrome仍是Safari if (/Chrome\/(\S+)/.test(ua)) { browser.ver = RegExp["$1"]; browser.chrome = parseFloat(browser.ver); } else if (/Version\/(\S+)/.test(ua)) { browser.ver = RegExp["$1"]; browser.safari = parseFloat(browser.ver); } else { // 近似的肯定版本號 var safariVersion = 1; if (engine.webkit < 100) { safariVersion = 1; } else if (engine.webkit < 312) { safariVersion = 1.2; } else if (engine.webkit < 412) { safariVersion = 1.3; } else { safariVersion = 2; } browser.safari = browser.ver = safariVersion; } } else if (/KHTML\/(\S+)/.test(ua) || /Konqueror\/([^;]+)/.test(ua)) { engine.ver = browser.ver = RegExp["$1"]; engine.khtml = browser.konq = parseFloat(engine.ver); } else if (/rv:([^\)]+)\) Gecko\/\d{8}/.test(ua)) { engine.ver = RegExp["$1"]; engine.gecko = parseFloat(engine.ver); // 肯定是否是Firefox瀏覽器 if (/Firefox\/(\S+)/.test(ua)) { browser.ver = RegExp["$1"]; browser.firefox = parseFloat(browser.ver); } } else if (/MSIE ([^;]+)/.test(ua)) { engine.ver = RegExp["$1"]; engine.ie = parseFloat(engine.ver); }
if (client.engine.webkit) { if (client.browser.chrome) { // 執行鍼對Chrome的代碼 } else if (client.browser.safari) { // 執行鍼對Safari的代碼 } } else if (client.engine.gecko) { if(client。browser.Firefox) { // 執行鍼對Firefox的代碼 } else { // 執行鍼對其餘Gecko瀏覽器代碼 } }
// 咱們的檢測代碼須要添加平臺的檢測 var client = function() { var engine = { // 呈現引擎 ie: 0, gecko: 0, webkit: 0, khtml: 0, opera: 0, // 具體的版本號 ver: null }; var browser = { // 瀏覽器 ie: 0, firefox: 0, safari: 0, konq: 0, opera: 0, chrome: 0, // 具體的版本號 ver: null } var system = { win: false, mac: false, // Unix x11: false } // 在此檢測呈現引擎、平臺和設備 ... return { engine: engine, browser: browser, system: system }; }();
navigator.platform
來肯定平臺,在不一樣瀏覽器中給出的值都是一致的,檢測起來很是直觀var p = navigator.platform; // window 可能有 Win32 和 Win64 system.win = p.indexOf("Win") == 0; system.win = p.indexOf("Mac") == 0; system.win = (p.indexOf("U11") == 0) || (p.indexOf("Linux") == 0);
版本 | IE 4+ | Gecko | Opera < 7 | Opera 7+ | WebKit |
---|---|---|---|---|---|
XP | "Windows NT 5.1" | "Windows NT 5.1" | "WindowsXP" | "Windows NT 5.1" | "Windows NT 5.1" |
Vista | "Windows NT 6.0" | "Windows NT 6.0" | n/a | "Windows NT 6.0" | "Windows NT 6.0" |
7 | "Windows NT 6.1" | "Windows NT 6.1" | n/a | "Windows NT 6.1" | "Windows NT 6.1" |
10 | "Windows NT 10.0" | "Windows NT 10.0" | n/a | "Windows NT 10.0" | "Windows NT 10.0" |
if (system.win) { // 好比在Windows10的Chrome裏,userAgent返回字符串 // Mozilla/5.0 (Windows NT 10.0; Win64; x64) ... // 咱們要提取兩個子字符串 'NT' 和 '10.0' // ([^dows]{2}) 表示排除包含'dows'的字符以後的後2位字符 加入捕獲組 $1 // (\d+\.\d+) 表示 x.x(x) 形式的版本號加入捕獲組 $2 if (/Windows ([^dows]{2})\s?(\d+\.\d+)?/.test(ua)) { if (RegExp["$1"] == "NT") { switch (RegExp["$2"]) { case "5.1": system.win = "XP"; break; case "6.0": system.win = "Vista"; break; case "6.1": system.win = "7"; break; case "10.0": system.win = "10"; break; default: system.win = "NT"; break; } } else { system.win = RegExp["$1"]; } } }
// 咱們在系統變量裏添加移動設備的屬性 var client = function() { ... var system = { win: false, mac: false, // Unix x11: false, // 移動設備 iphone: false, ipod: false, ipad: false, ios: false, android: false, nokiaN: false, winMobile: false } // 在此檢測呈現引擎、平臺和設備 ... return { engine: engine, browser: browser, system: system }; }();
system.iphone = ua.indexOf("iPhone") > -1; system.ipod = ua.indexOf("iPod") > -1; system.ipad = ua.indexOf("iPad") > -1;
system.ios
中都不會是 0// 檢測iOS版本 if (system.max && ua.indexOf("Mobile") > -1) { if (/CPU (?:iPhone )?OS (\d+_\d+)/.test(ua)) { system.ios = parseFloat(RegExp.$1.repalce("_", ".")); } else { system.ios = 2; // 不能準確判斷只能靠猜 } }
// 檢測Android版本 if (/Android (\d+\.\d+)/.test(ua)) { system.android = parseFloat(RegExp.$1); }
Opera/9.10 (Nintendo Wii;U; ; 1621; en)
Mozilla/5.0 (PLAYSTATION 3; 2.00)
// 咱們在系統變量裏添加遊戲設備的屬性 var client = function() { ... var system = { ... // 遊戲系統 wii: false, ps: false } // 在此檢測呈現引擎、平臺和設備 ... return { engine: engine, browser: browser, system: system }; }();
system.wii = ua.indexOf("Wii") > -1; // ps要忽略大小寫 system.ps = /playstation/i.test(ua);
// 我的作了部分修改 修改時間 2019.5.17 var client = function() { var engine = { // 呈現引擎 ie: 0, gecko: 0, webkit: 0, khtml: 0, opera: 0, // 具體的版本號 ver: null }; var browser = { // 瀏覽器 ie: 0, firefox: 0, safari: 0, konq: 0, opera: 0, chrome: 0, // 具體的版本號 ver: null } var system = { win: false, mac: false, // Unix x11: false, // 移動設備 iphone: false, ipod: false, ipad: false, ios: false, android: false, nokiaN: false, winMobile: false, // 遊戲系統 wii: false, ps: false } // 在此檢測呈現引擎、平臺和設備 var ua = navigator.userAgent; if (window.opera) { engine.ver = browser.ver = window.opera.version(); engine.opera = browser.opera = parseFloat(engine.ver); } else if (/AppleWebKit\/(\S+)/.test(ua)) { engine.ver = RegExp["$1"]; engine.webkit = parseFloat(engine.ver); // 肯定是Chrome仍是Safari if (/Chrome\/(\S+)/.test(ua)) { browser.ver = RegExp["$1"]; browser.chrome = parseFloat(browser.ver); } else if (/Version\/(\S+)/.test(ua)) { browser.ver = RegExp["$1"]; browser.safari = parseFloat(browser.ver); } else { // 近似的肯定版本號 var safariVersion = 1; if (engine.webkit < 100) { safariVersion = 1; } else if (engine.webkit < 312) { safariVersion = 1.2; } else if (engine.webkit < 412) { safariVersion = 1.3; } else { safariVersion = 2; } browser.safari = browser.ver = safariVersion; } } else if (/KHTML\/(\S+)/.test(ua) || /Konqueror\/([^;]+)/.test(ua)) { engine.ver = browser.ver = RegExp["$1"]; engine.khtml = browser.konq = parseFloat(engine.ver); } else if (/rv:([^\)]+)\) Gecko\/\d{8}/.test(ua)) { engine.ver = RegExp["$1"]; engine.gecko = parseFloat(engine.ver); // 肯定是否是Firefox瀏覽器 if (/Firefox\/(\S+)/.test(ua)) { browser.ver = RegExp["$1"]; browser.firefox = parseFloat(browser.ver); } } else if (/MSIE ([^;]+)/.test(ua)) { engine.ver = RegExp["$1"]; engine.ie = parseFloat(engine.ver); } // 檢測瀏覽器 browser.ie = engine.ie; browser.opera = engine.opera; // 檢測平臺 var p = navigator.platform; system.win = p.indexOf("Win") == 0; system.win = p.indexOf("Mac") == 0; system.win = (p.indexOf("U11") == 0) || (p.indexOf("Linux") == 0); // 檢測Windos操做系統 // 排除WindosXP之前的系統 if (system.win) { if (/Windows ([^dows]{2})\s?(\d+\.\d+)?/.test(ua)) { if (RegExp["$1"] == "NT") { switch (RegExp["$2"]) { case "5.1": system.win = "XP"; break; case "6.0": system.win = "Vista"; break; case "6.1": system.win = "7"; break; case "10.0": system.win = "10"; break; default: system.win = "NT"; break; } } else { system.win = RegExp["$1"]; } } } // 移動設備 // 剔除了諾基亞和windows phone system.iphone = ua.indexOf("iPhone") > -1; system.ipod = ua.indexOf("iPod") > -1; system.ipad = ua.indexOf("iPad") > -1; // 檢測iOS版本 if (system.max && ua.indexOf("Mobile") > -1) { if (/CPU (?:iPhone )?OS (\d+_\d+)/.test(ua)) { system.ios = parseFloat(RegExp.$1.repalce("_", ".")); } else { system.ios = 2; // 不能準確判斷只能靠猜 } } // 檢測Android版本 if (/Android (\d+\.\d+)/.test(ua)) { system.android = parseFloat(RegExp.$1); } // 遊戲系統 system.wii = ua.indexOf("Wii") > -1; system.ps = /playstation/i.test(ua); return { engine: engine, browser: browser, system: system }; }();
用戶代理檢測是客戶端檢測的最後一個選項。只要可能,都應該優先採用能力檢測和怪癖檢測。用戶代理檢測通常適用於下列情形:html