一、前言                              
 
  苦逼的前端攻城狮都深受兼容之苦,再完成每一项功能前都要左顾右盼,生怕浏览器不支持某个API,生怕原生API内含臭虫因此判断浏览器类型和版本号成了不可绕过的一道关卡,而特征嗅探是继浏览器探测后另一利器处理上述问题。
 
 
 
二、何为特征嗅探                                
 
 从前我们都是通过对navigator.userAgent或navigator.appName两个属性值进行特定字符串匹配和萃取来区分浏览器类型和获取版本号的。但随着IE8提供可选的文档兼容性模式设置和各种加壳浏览器的出现,导致无法通过navigator.userAgent和navigator.appName的属性值准确判断浏览器实际提供的API特性和文档模式,于是就出现特征嗅探的做法。其实特征嗅探就是解决两种问题,第一、是否支持某特性;第二、当前的文档模式是什么(注意是文档模式,不是浏览器版本号)。
 
   而著名的 var isLteIE8 = !+[1,];就是判断是否处于IE5678的文档模式下的特征嗅探。
 
 
 
三、判断IE当前的文档模式                            
 
复制代码
// 判断是否为IE
var isIE = navtigator.userAgent.toLocaleLowerCase().indexOf('msie') !== -1;
// 判断是否为IE5678
var isLteIE8 = isIE && !+[1,];
// 用于防止因通过IE8+的文档兼容性模式设置文档模式,导致版本判断失效
var dm = document.documentMode, 
  isIE5, isIE6, isIE7, isIE8, isIE9, isIE10, isIE11;
if (dm){
  isIE5 = dm === 5;
  isIE6 = dm === 6;
  isIE7 = dm === 7;
  isIE8 = dm === 8;
  isIE9 = dm === 9;
  isIE10 = dm === 10;
  isIE11 = dm === 11;
}
else{
    // 判断是否为IE5,IE5的文本模式为怪异模式(quirks)
isIE5 = (isLteIE8 && document.compatMode === 'BackCompat');
 
  // 判断是否为IE6,IE7开始有XMLHttpRequest对象
  isIE6 = isLteIE8 && !isIE5 && !XMLHttpRequest;
 
  // 判断是否为IE7,IE8开始有document.documentMode属性
  isIE7 = isLteIE8 && !isIE6 && !document.documentMode;
 
  // 判断是否IE8
  isIE8 = isLteIE8 && document.documentMode;
 
  // 判断IE9,IE10开始支持严格模式,严格模式中函数内部this为undefined
  isIE9 = !isLteIE8 && (function(){
    "use strict";
      return !!this;
  }());
 
  // 判断IE10,IE11开始移除了attachEvent属性
  isIE10 = isIE && !!document.attachEvent && (function(){
    "use strict";
      return !this;
  }());
    
  // 判断IE11
  isIE11 = isIE && !document.attachEvent;
}
复制代码
  注意:若通过IE8+通过指定文档兼容性模式的方式,设置为IE6的文档模式,那么上述的 var isIE6 = isLteIE8 && !isIE5 && !XMLHttpRequest 将判断错误,因为这时XMLHttpRequest是存在的,这是由于文档兼容性模式仅仅是尽量模拟旧版本浏览器而已,不完全等同于旧版本浏览器。所以可直接通过document.documentMode来判断当前文档模式。