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