1. firefox 
gecko是firefox的呈现引擎。当初的gecko是作为通用mozilla浏览器一部分开发的,而第一个采用gecko引擎的浏览器是netscape6;
我们可以使用用户代理检测下:如下js代码:
var ua = navigator.useragent;console.log(ua);
在windows下firefox下打印如下:
复制代码 代码如下:
mozilla/5.0 (windows nt 6.1; wow64; rv:38.0) gecko/20100101 firefox/38.0
上述是为netscape6编写的代理字符串一些构成:如下:
  mozilla/mozilla版本号(平台;加密类型;操作系统或cpu;预先发行的版本;gecko/gecko版本号;应用程序或产品/应用程序或产品版本号);2. safari
 safari的呈现引擎是webkit;是linux平台中konqueror浏览器的呈现引擎khtml的一个分支;几年后,webkit独立出来成为一个开源项目,专注于呈现引擎开发;
如下代码:
var ua = navigator.useragent;console.log(ua);
在windows下safari下打印如下:
复制代码 代码如下:
mozilla/5.0 (windows nt 6.1; wow64) applewebkit/534.57.2 (khtml, like gecko) version/5.1.7 safari/534.57.2
webkit的用户代理字符串具备如下格式:
  mozilla/5.0 (平台;加密类型;操作系统或cpu) applewebkit/applewebkit版本号(khtml,like gecko) safari/safari版本号;3. chrome
谷歌公司的chrome浏览器以webkit作为呈现引擎,使用了不同的javascript引擎;
如下js代码:
var ua = navigator.useragent;console.log(ua);
在windows下chrome下打印如下:
复制代码 代码如下:
mozilla/5.0 (windows nt 6.1; wow64) applewebkit/537.36 (khtml, like gecko) chrome/42.0.2311.152 safari/537.36
用户代理字符串完全自取webkit,只添加了一段表示chrome版本号信息;格式如下:
  mozilla/5.0 (平台;加密类型;操作系统或cpu) applewebkit/applewebkit版本号(khtml,like gecko) chrome/chrome版本号 safari/safari版本号4.  opera
opera默认的用户代理字符串是所有现代浏览器中最合理的---正确地标识了自身极其版本号,在opera8.0之前;其用户代理字符串采用如下格式:
  opera/ 版本号 (操作系统或cpu;加密类型) [语言]  opera8发布后,用户代理字符串的 “语言”部分被移到圆括号内,以便更好地与其他浏览器匹配;如下所示:  opera/版本号 (操作系统或cpu;加密类型;语言)在现在的最新的版本opera29,
如下js代码:
var ua = navigator.useragent;console.log(ua);
通过代理检测如下:
复制代码 代码如下:
mozilla/5.0 (windows nt 6.1; wow64) applewebkit/537.36 (khtml, like gecko) chrome/42.0.2311.152 safari/537.36 opr/29.0.1795.60;
5.  ie
自从ie3以来,微软已经将ie的用户代理字符串修改成兼容netscape的形式,结构如下:
mozilla/版本号(平台;加密类型;操作系统或cpu);
但是ie8+的用户代理字符串添加了呈现引擎的(trident)的版本号;
js代码如下:
var ua = navigator.useragent.tolowercase();console.log(ua);
比如在window下 ie7的如下:
复制代码 代码如下:
mozilla/4.0 (compatible; msie 7.0; windows nt 6.1; wow64; trident/7.0; slcc2; .net clr 2.0.50727; .net clr 3.5.30729; .net clr 3.0.30729; media center pc 6.0; infopath.3; .net4.0c; .net4.0e)
ie8的如下:
复制代码 代码如下:
mozilla/4.0 (compatible; msie 8.0; windows nt 6.1; wow64; trident/7.0; slcc2; .net clr 2.0.50727; .net clr 3.5.30729; .net clr 3.0.30729; media center pc 6.0; infopath.3; .net4.0c; .net4.0e)
但是ie9+ 对字符串的格式做了一点调整;mozilla的版本号增加到5.0;
ie9的如下:
复制代码 代码如下:
mozilla/5.0 (compatible; msie 9.0; windows nt 6.1; wow64; trident/7.0; slcc2; .net clr 2.0.50727; .net clr 3.5.30729; .net clr 3.0.30729; media center pc 6.0; infopath.3; .net4.0c; .net4.0e)
ie10的如下:
    复制代码 代码如下:
mozilla/5.0 (compatible; msie 10.0; windows nt 6.1; wow64; trident/7.0; slcc2; .net clr 2.0.50727; .net clr 3.5.30729; .net clr 3.0.30729; media center pc 6.0; infopath.3; .net4.0c; .net4.0e)
ie11的如下:
复制代码 代码如下:
mozilla/5.0 (windows nt 6.1; wow64; trident/7.0; slcc2; .net clr 2.0.50727; .net clr 3.5.30729; .net clr 3.0.30729; media center pc 6.0; infopath.3; .net4.0c; .net4.0e; rv:11.0) like gecko
6. ios和android
移动操作系统ios和android默认的浏览器都是基于webkit;而且都像桌面版一样;共享相同的基本用户代理字符串格式;ios设备的基本格式如下:
  mozilla/5.0 (平台;加密类型;操作系统或cpu like mac os x;语言)  applewebkit/ applewebkit版本号(khtml,like gecko) version/浏览器版本号  mobile/移动版本号 safari/safari版本号android浏览器中默认格式与ios格式相似,没有移动版本号(但有mobile记号):
  mozilla/5.0 (linux; u; android 2.2; en-us; nexus one build/frf91)  applewebkit/533.1 (khtml, like gecko) version/4.0 mobile safari/533.17. konqueror
与kde linux 集成的konqueror,是一款基于khtml 开源呈现引擎的浏览器。尽管konqueror 只
能在linux 中使用,但它也有数量可观的用户。为确保最大限度的兼容性,konqueror 效仿ie 选择了如
下用户代理字符串格式:
  mozilla/5.0 (compatible; konqueror/ 版本号; 操作系统或cpu )不过,为了与webkit 的用户代理字符串的变化保持一致,konqueror 3.2 又有了变化,以如下格式
将自己标识为khtml:
  mozilla/5.0 (compatible; konqueror/ 版本号; 操作系统或cpu) khtml/ khtml 版本号 (like gecko)下面是一个例子:
复制代码 代码如下:
mozilla/5.0 (compatible; konqueror/3.5; sunos) khtml/3.5.0 (like gecko)
用户代理字符串检测技术
识别呈现引擎;
下面我们主要检测五大呈现引擎:ie,gecko,webkit,khtml和opera
如下代码:
var client = function(){  var engine = {    // 呈现引擎    ie: 0,    gecko:0,    webkit: 0,    khtml:0,    opera:0,    //其他版本号    ver: null  };  // 在此检测呈现引擎,平台和设备  return {    engine: engine  };}();
在如上client对象字面量中,每个呈现引擎都对应着一个属性,属性值默认为0;如果检测到了那个呈现引擎,那么将以浮点数值形式将引擎的版本号写入相应的属性。而呈现引擎的完整版本被写入变量ver属性中;
要正确识别呈现引擎,关键是检测顺序要正确,用户代理字符串存在诸多不一致的地方,如果检测顺序不对,很可能会导致检测结果不正确,因此,第一步就是识别opera,因为它的用户代理字符串有可能模仿其他浏览器;目前最新的opera浏览器版本是29,所以如下:
var ua = navigator.useragent .tolowercase();console.log(ua);
打印如下:
复制代码 代码如下:
mozilla/5.0 (windows nt 6.1; wow64) applewebkit/537.36 (khtml, like gecko) chrome/42.0.2311.152 safari/537.36 opr/29.0.1795.60
因此可以这样判断代码;如下:
var ua = navigator.useragent.tolowercase();if(ua.match(/opr\/([\d\.]+)/)) {  var result = ua.match(/opr\/([\d\.]+)/);  console.log(result)  console.log(result[1])}
执行如下:
console.log(result);打印如下:
复制代码 代码如下:
[opr/29.0.1795.60, 29.0.1795.60, index: 110, input: mozilla/5.0 (windows nt 6.1; wow64) applewebkit/53…rome/42.0.2311.152 safari/537.36 opr/29.0.1795.60];
console.log(result[1])打印如下:
复制代码 代码如下:
29.0.1795.60
由此;我们可以这样编写代码;如下:
var ua = navigator.useragent.tolowercase();if(ua.match(/opr\/([\d\.]+)/)) {  var result = ua.match(/opr\/([\d\.]+)/);  engine.ver = result[1];  engine.opera = parsefloat(engine.ver);}
现在我们来打印下console.log(engine);如下所示:
但是呢opera29之前的版本, opera5+也有window.opera对象,所以我们也必须检测window.opera对象,我们可以调用version()方法可以返回一个表示浏览器版本的字符串;如下代码:
if(window.opera) {  engine.ver = window.opera.version();  engine.opera = parsefloat(engine.ver);}
现在我们为了兼容之前及之后的opera浏览器,我们可以综合一下;如下:
var engine = client;var ua = navigator.useragent.tolowercase();if(ua.match(/opr\/([\d\.]+)/) || window.opera) {  var result = ua.match(/opr\/([\d\.]+)/);  engine.ver = result[1];  engine.opera = parsefloat(engine.ver);  if(window.opera) {    engine.ver = window.opera.version();    engine.opera = parsefloat(engine.ver);  }}
现在第二步需要检测的是引擎是webkit,因为webkit的用户代理字符串中包含”gecko”和”khtml”这两个字符串,如果检测这两个,可能会有误差,但是webkit的用户代理字符串中的”applewebkit”是独一无二的,因此可以根据这个来检测;
var engine = client;var ua = navigator.useragent.tolowercase();if(/applewebkit\/(\s+)/.test(ua)) {  engine.ver = regexp[$1];  engine.webkit = parsefloat(engine.ver);}
因此综合以上的所有代码如下:
var engine = client;var ua = navigator.useragent.tolowercase();if(ua.match(/opr\/([\d\.]+)/) || window.opera) {  var result = ua.match(/opr\/([\d\.]+)/);  engine.ver = result[1];  engine.opera = parsefloat(engine.ver);  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);}
接下来要测试的呈现引擎是khtml,同样,khtml的用户代理字符串中也包含”gecko”,因此在排除khtml之前,我们无法准确检测基于gecko浏览器。khtml的版本号与webkit的版本号在用户代理字符串中的格式差不多,因此也可以使用正则表达式,此外,由于konqueror 3.1 及更早版本中不包含khtml 的版本,故而就要使用konqueror 的版本来代替。下面就是相应的检测代码。
if (/khtml\/(\s+)/.test(ua) || /konqueror\/([^;]+)/.test(ua)){  engine.ver = regexp[$1];  engine.khtml = parsefloat(engine.ver);}
下面是所有的代码:
var engine = client;var ua = navigator.useragent.tolowercase();if(ua.match(/opr\/([\d\.]+)/) || window.opera) {  var result = ua.match(/opr\/([\d\.]+)/);  engine.ver = result[1];  engine.opera = parsefloat(engine.ver);  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);}
在排除webkit和khtml后,就可以准确检测gecko了,但是在用户代理字符串中,gecko的版本号不会出现在字符串”gecko”的后面,而是会出现在字符串”rv:”的后面。因此必须使用一个更复杂的正则表达式;
比如 firefox下的用户代理如下:
复制代码 代码如下:
mozilla/5.0 (windows nt 6.1; wow64; rv:38.0) gecko/20100101 firefox/38.0
如下js代码检测:
var engine = client;var ua = navigator.useragent.tolowercase();if(/rv:([^\)]+)\) gecko\/\d{8}/.test(ua)){  engine.ver = regexp[$1];  engine.gecko = parsefloat(engine.ver);}
所以所有的js代码如下:
var engine = client;var ua = navigator.useragent.tolowercase();if(ua.match(/opr\/([\d\.]+)/) || window.opera) {  var result = ua.match(/opr\/([\d\.]+)/);  engine.ver = result[1];  engine.opera = parsefloat(engine.ver);  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);}
最后一个检测就是ie浏览器了,ie的版本号位于字符串”msie”的后面,一个分号的前面;如下:
复制代码 代码如下:
mozilla/5.0 (compatible; msie 9.0; windows nt 6.1; wow64; trident/7.0; slcc2; .net clr 2.0.50727; .net clr 3.5.30729; .net clr 3.0.30729; media center pc 6.0; infopath.3; .net4.0c; .net4.0e)
如下js代码检测:
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  };  // 在此检测呈现引擎,平台和设备  return {    engine: engine  };}();var engine = client;var ua = navigator.useragent.tolowercase();if(ua.match(/opr\/([\d\.]+)/) || window.opera) {  var result = ua.match(/opr\/([\d\.]+)/);  engine.ver = result[1];  engine.opera = parsefloat(engine.ver);  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);}
识别浏览器
大多数情况下,如上面识别了引擎还不能满足我们的需求,比如苹果公司的safari浏览器和谷歌的chrome浏览器都使用了webkit作为呈现引擎;但他们的javascript引擎且不一样,在这两个浏览器中,client.webkit都会返回非0值,无法区别,因此我们还需要识别下浏览器;
如下增加代码如下:
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    };}();
如上代码增加了私有变量browser,用于保存每个主要浏览器的属性,与engine变量一样,除了当前使用的浏览器,其他属性值将保持为0;如果是当前使用的浏览器,则这个属性中保存的是浮点数值形式的版本号,同样browser中的ver属性中在必要时将包含字符串形式的浏览器完整版本号;
因此封装后的所有js代码如下:
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 engine = client;var browser = client;var ua = navigator.useragent.tolowercase();if(ua.match(/opr\/([\d\.]+)/) || window.opera) {  var result = ua.match(/opr\/([\d\.]+)/);  engine.ver = browser.ver = result[1];  engine.opera = browser.opera = parsefloat(engine.ver);  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  /*   * chrome用户代理字符串   * mozilla/5.0 (windows nt 6.1; wow64)    applewebkit/537.36 (khtml, like gecko)    * chrome/42.0.2311.152 safari/537.36   */  if(/chrome\/(\s+)/.test(ua)) {    browser.ver = regexp[$1];    browser.chrome = parsefloat(browser.ver);  }else if(/version\/(\s+)/.test(ua)) {    /*     * safari用户代理字符串     * mozilla/5.0 (windows nt 6.1; wow64) applewebkit/534.57.2 (khtml, like gecko)      * version/5.1.7 safari/534.57.2     */    browser.ver = regexp[$1];    browser.safari = parsefloat(browser.ver);  }else {    //近似地确定版本号    var safariversion = 1;    if (engine.webkit < 100){      safariversion = 1;    } else if (engine.webkit  -1;system.ipad = ua.indexof(“ipad”) > -1; 
除了知道ios 设备,最好还能知道ios 的版本号。在ios 3 之前,用户代理字符串中只包含cpu like  mac os,后来iphone 中又改成cpu iphone os 3_0 like mac os x,ipad 中又改成cpu os 3_2  like mac os x。也就是说,检测ios 需要正则表达式反映这些变化。//检测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; //不能真正检测出来,所以只能猜测  }}
检查系统是不是mac os、字符串中是否存在mobile,可以保证无论是什么版本,system.ios  中都不会是0。然后,再使用正则表达式确定是否存在ios 的版本号。如果有,将system.ios 设置为  表示版本号的浮点值;否则,将版本设置为2。(因为没有办法确定到底是什么版本,所以设置为更早的  版本比较稳妥。)  检测android 操作系统也很简单,也就是搜索字符串android并取得紧随其后的版本号。//检测android 版本if (/android (\d+\.\d+)/.test(ua)){   system.android = parsefloat(regexp.$1);}
由于所有版本的android 都有版本值,因此这个正则表达式可以精确地检测所有版本,并将  system.android 设置为正确的值。  在了解这些设备信息的基础上,就可以通过下列代码来确定用户使用的是什么设备中的webkit 来访问网页:
if (client.engine.webkit){  if (client.system.ios){     //ios 手机的内容  } else if (client.system.android){    //android 手机的内容  } }
因此所有的js代码如下:
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,       xll: false,       // 移动设备       iphone: false,       ipod: false,       ipad: false,       ios: false,       android:false      };      // 在此检测呈现引擎,平台和设备      return {        engine: engine,        browser: browser,        system: system      };    }();    var engine = client;    var browser = client;    var ua = navigator.useragent.tolowercase();    if(ua.match(/opr\/([\d\.]+)/) || window.opera) {      var result = ua.match(/opr\/([\d\.]+)/);      engine.ver = browser.ver = result[1];      engine.opera = browser.opera = parsefloat(engine.ver);      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      /*       * chrome用户代理字符串       * mozilla/5.0 (windows nt 6.1; wow64) applewebkit/537.36 (khtml, like gecko)        * chrome/42.0.2311.152 safari/537.36       */       if(/chrome\/(\s+)/.test(ua)) {         browser.ver = regexp[$1];         browser.chrome = parsefloat(browser.ver);       }else if(/version\/(\s+)/.test(ua)) {         /*          * safari用户代理字符串          * mozilla/5.0 (windows nt 6.1; wow64) applewebkit/534.57.2 (khtml, like gecko)           * version/5.1.7 safari/534.57.2          */         browser.ver = regexp[$1];         browser.safari = parsefloat(browser.ver);       }else {         //近似地确定版本号         var safariversion = 1;         if (engine.webkit  -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);     }
   
 
   