JS 判断 IE 版本的另类解决方案

jQuery 在 1.9 版本之前,提供了一个浏览器对象检测的属性 $.browser,使用率极高。但是在 1.9 版本发布之后,大家钟爱的这个属性被 jQuery 无情的抛弃了。大家开始着手寻找 $.browser 的替代方案。于是各种利用 IE bug 的检测方法被搜了出来:

// shortest from a Russian
var ie = !-[1,]

// Option from Dean Edwards:
var ie = /*@cc_on!@*/false

// Use the commented line:
var ie//@cc_on=1

// Variation (shorter variable):
var ie = '\v'=='v'

// Option to Gareth Hayes (former record-holder):
var ie = !+"\v1"

还有一些比较传统的做法是通过读取 navigator.userAgent 的方式加以判断。比较少见的是从 HTML 特殊注释入手,比如官方的 HTML hack 方式有:

<!--[if IE]>
// 全部IE版本可见
<![endif]-->
<!--[if IE 6]>
// IE6可见
<![endif]-->

这样的写法在其它浏览器里,完全就是一坨注释而直接遭到无视,但在 IE 里却不会。IE 会分析里面的提到的版本号,并根据版本号确定要不要解析里面的 DOM 元素和文本内容。等一下!DOM元素?那岂不是可以使用js来获取里面的 DOM 元素?反正谁看到了,谁就是 IE!于是,国外大神就有了下面的写法:

var isIE = function(){
    var b = document.createElement('b')
    b.innerHTML = '<!--[if IE]><i></i><![endif]-->'
    return b.getElementsByTagName('i').length === 1
}

这也太巧妙了!首先生成了一个 b 元素,设置它的 innerHTML 为一坨只有 IE 才认识的注释,注释里只有一个空的标签,然后读取里面的出现的元素i的个数是不是等于 1,是不是等于 1,是不是等于 1。。。。 在我看来,这样的写法比其它任何一种都要好。至于为什么生成一个 b 元素并且里面写一个 i 元素而不是 div 或者 strong,更多是考虑到前者字节量更小。 检测各个 IE 版本的方法也就顺理成章了:

var isIE6 = function(){
    var b = document.createElement('b')
    b.innerHTML = '<!--[if IE 6]><i></i><![endif]-->'
    return b.getElementsByTagName('i').length === 1
}
// var isIE7
// ...

更进一步可抽象成:

var isIE = function(ver){
    var b = document.createElement('b')
    b.innerHTML = '<!--[if IE ' + ver + ']><i></i><![endif]-->'
    return b.getElementsByTagName('i').length === 1
}

if(isIE(6)){
    // IE 6
}

if(isIE(9)){
    // IE 9
}

这样想检测哪个版本都毫无压力。但是,如果只想检测是不是 IE,而不关心浏览器版本,那只需要在调用函数的时候,不传递参数即可:

var ie  = isIE()
View on GitHub