每篇文章纯属个人经验观点,如有错误疏漏欢迎指正
navigator
对象中包含了用户所使用的浏览器以及操作系统等信息,我们可以通过查询相关信息从而让我们的系统能够与浏览器及操作系统兼容。 尽管我们现在几乎已经不需要在面对 IE6
这种史诗级级别的浏览器,但在IE10
以下的浏览器仍存在一些问题,对一些特性并不能起到很好的支持。例如说 IE8/9
并不支持 FormData
,这就在文件上传时给我们造成了一定的麻烦。如果没有兼容低版本浏览器的打算,可以直接通过 navigator
来检测浏览器的版本,来提示用户更换高版本的浏览器以访问系统。
一、Navigator 属性和方法
主要属性:
appCodeName
返回浏览器的代码名;
所有以 Netscape
代码为基础和 Microsoft
的浏览器中,返回 Mozilla
,有少部分浏览器会返回 Gecko
。
appVersion
返回浏览器版本信息;
返回的内容包括用户的操作系统及版本、浏览器使用的网页排版引擎、浏览器内核及版本等。且不同浏览器返回的格式是不同的。
appName
返回浏览器的完整名称;
在基于 Netscape
的浏览器中,返回 Netscape
。在 IE
中,返回 Microsoft Internet Explorer
。其他浏览器可以正确地表示自己或者伪装成其他的浏览器以达到兼容性。所以我们并不能通过该属性获得正确的浏览器名称。
cookieEnabled
表示浏览器cookie
是否允许使用;
用户可以手动设置是否允许使用 cookie
,该属性值为 true
表示允许使用。
language
浏览器的主语言;
中文返回 zh-CN
,H5新增了 languages
属性,会返回一个数组来表示网站访客所使用的语言,比如 Chrome
会返回 ["zh-CN", "zh", "en"]
。
onLine
表示浏览器是否连接到了因特网;
返回一个布尔值来表明浏览器是否联网。
platform
返回浏览器所在的系统平台;
windows
会返回 win32
等。
plugins
浏览器中安装的插件信息的数组;userAgent
返回浏览器的用户代理字符串;
其他属性和方法
appMinorVersion
返回浏览器次版本信息;
只有IE
浏览器支持该属性,FireFox
、Chrome
、Edge
均返回 undefined
。
buildID
返回浏览器编译版本;cpuClass
返回客户端CPU
类型;mimeTypes
在浏览器中注册的MIME
类型数组;oscpu
客户端计算机的操作系统或使用的CPU
;product
产品名称(如Gecko
);productSub
关于产品的次要信息(如Gecko
的版本);systemLanguage
操作系统的语言;userLanguage
操作系统的默认语言;userProfile
借以访问用户个人信息的对象;vendor
浏览器的品牌;vendorSub
有关供应商的次要信息;
貌似只有 Firefox
支持该属性,格式为 20181001000000
。
javaEnabled()
表示当前浏览器中是否启用了Java 4
;preference()
设置用户的首选项;register-ContentHandler()
针对特定的MIME类型将一个站点注册为处理程序;register-ProtocolHandler()
针对特定的协议将一个站点注册为处理程序;
二、实际应用
检测浏览器类型
浏览器在发送 HTTP
请求时,会在请求头附带一个具有 user-agent
(用户代理)的字符串,其中包含了浏览器的名称和版本等信息,可以通过用户代理字符串检测浏览器类型。
另外 IE11
中 userAgent
已经不包含 msie
所以需要根据 Trident
来进行相关判断:
/*** 获取浏览器类型* @description 不能用于判断 360 等套壳浏览器* @returns {String} 浏览器名称*/function getBrowser() { var ua = navigator.userAgent.toLowerCase(); if (/msie/.test(ua) && !/opera/.test(ua) || /(trident)/.test(ua)) { return "IE"; } else if (/opera/.test(ua)) { return "Opera"; } else if (/edge/.test(ua)) { return "Edge"; } else if (/version.*safari/.test(ua)) { return "Safari"; } else if (/chrome/.test(ua)) { return "Chrome"; } else if (/gecko/.test(ua) && !/webkit/.test(ua)) { return "Firefox"; }else{ return "Other Browser"; }}
检测浏览器版本
一般我们只需要来检测 IE
的浏览器版本,因为其它的浏览器都能提供很好的兼容性,并不需要刻意的去处理,而IE
浏览器会在 MSIE
字符串后面带一个空格,然后跟随版本号及分号,根据这一点我们可以直接截取出浏览器的版本
/*** 获取IE浏览器版本* @description 0 代表浏览器版本过低或 "Other Browser"* @returns {Number} IE浏览器版本*/function getIEVersion() { var ua = navigator.userAgent.toLowerCase(); if (/msie/.test(ua) && !/opera/.test(ua)) { var index = ua.indexOf("msie"); return parseFloat(ua.substring(index + 5, ua.indexOf(";", index))); // 直接截取截取版本号 } else if (/(trident)/.test(ua)) { return "11"; // IE11 需要特殊处理 } else { return "0" // 0 代表浏览器版本过低或 "Other Browser"; } }
关于套壳浏览器
目前并没有任何一个方法可以准确的分辨出用户是否在使用套壳浏览器。在早些年前,我们还可以通过 userAgent
来进行判断,但后来这些浏览器将 userAgent
伪装的和 IE
或者 Chrome
一模一样,且版本号也和它们保持了一致,导致我们根本无法通过用户代理对他们进行分辨。
关于360浏览器
以360浏览器为例,它最坑的地方在于当你去360的官网或其它合作网站时,它的userAgent
会附带着明显的浏览器标志:360SE
代表着360安全浏览器, 360EE
代表着360极速浏览器:
下图360安全浏览器在百度和360官网为例:
在其官网下,明确带有 QIHU 360SE
的字样:
这就是360最坑的地方,在别人的网站下返回的都是标准的谷歌浏览器的用户代理,在自己的网站下就有自己的标识。除非开发人员所在公司与360有相关的合作,否则几乎没有一种方法来分辨它们。
以前可以凭借每个版本的360都有不同的差异点可以让我们籍此来加以分辨,但随着版本的更新,没有任何一个办法可以长期使用。
完整的检测方法
JS高级程序设计提供了一个可以完整检测用户代理字符串的代码,包括检测呈现引擎、平台、Windows 操作系统、移动设备和游戏系统:
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, 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 = browser.ver = RegExp["$1"]; engine.ie = browser.ie = parseFloat(engine.ver); } //检测浏览器 browser.ie = engine.ie; browser.opera = engine.opera; //检测平台 var p = navigator.platform; system.win = p.indexOf("Win") == 0; system.mac = p.indexOf("Mac") == 0; system.x11 = (p == "X11") || (p.indexOf("Linux") == 0); //检测 Windows 操作系统 if (system.win) { if (/Win(?:dows )?([^do]{2})\s?(\d+\.\d+)?/.test(ua)) { if (RegExp["$1"] == "NT") { switch (RegExp["$2"]) { case "5.0": system.win = "2000"; break; case "5.1": system.win = "XP"; break; case "6.0": system.win = "Vista"; break; case "6.1": system.win = "7"; break; default: system.win = "NT"; break; } } else if (RegExp["$1"] == "9x") { system.win = "ME"; } else { system.win = RegExp["$1"]; } } } //移动设备system.iphone = ua.indexOf("iPhone") > -1; system.ipod = ua.indexOf("iPod") > -1; system.ipad = ua.indexOf("iPad") > -1; system.nokiaN = ua.indexOf("NokiaN") > -1; //windows mobile if (system.win == "CE") { system.winMobile = system.win; } else if (system.win == "Ph") { if (/Windows Phone OS (\d+.\d+)/.test(ua)) { ; system.win = "Phone"; system.winMobile = parseFloat(RegExp["$1"]); } } //检测 iOS 版本 if (system.mac && ua.indexOf("Mobile") > -1) { if (/CPU (?:iPhone )?OS (\d+_\d+)/.test(ua)) { system.ios = parseFloat(RegExp.$1.replace("_", ".")); } 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 };}();
书中建议我们优先采用能力检测和怪癖检测,上述代码一般适用于以下几种情况:
不能直接准确地使用能力检测或怪癖检测。例如,某些浏览器实现了为将来功能预留的存根(stub)函数。在这种情况下,仅测试相应的函数是否存在还得不到足够的信息;
同一款浏览器在不同平台下具备不同的能力。这时候,可能就有必要确定浏览器位于哪个平台下;
为了跟踪分析等目的需要知道确切的浏览器;
每篇文章纯属个人经验观点,如有错误疏漏欢迎指正。转载请附带作者信息及出处。您的评论和关注是我更新的动力!
点击查看原文跳转到 博客 点下再看,少个BUG