JavaScript IE检测,为什么不使用简单的条件注释?

47
为了检测IE,大多数JavaScript库都会进行各种技巧。
  • jQuery似乎会向您页面的DOM添加临时对象以检测某些功能,
  • YUI2在其YAHOO.env.ua = function()中对用户代理进行正则表达式匹配(文件yahoo.js)。
阅读此答案后,我想到这是真的,在JavaScript中,为了简单地检测IE,我们可以简单地将以下内容添加到我们的页面中:
<!--[if IE]><script type="text/javascript">window['isIE'] = true;</script><![endif]-->

<script type="text/javascript" src="all-your-other-scripts-here.js"></script>

现在,通过简单的操作:

window.isIE 变量已经为我们所有的 JavaScript 代码设置好了。

if(window.isIE)
   ...

除了需要在所有页面中添加这个功能可能会很麻烦之外,还有我可能不知道的任何问题/考虑因素吗?


提醒您:我知道使用对象检测而不是浏览器检测更好,但仍有一些情况需要使用浏览器检测。


JS库尝试使用JavaScript来检测IE的一个主要原因是,使用条件注释需要向页面添加另一个脚本(而且这个脚本看起来很奇怪)。这可能会让一些人(新手程序员)感到困惑,或者让其他人感到烦恼。 - jhartz
1
您忘记在条件注释中关闭SCRIPT元素... - Šime Vidas
@Marcel Korpel:谢谢,聪明的代码片段,但我不同意向DOM添加DIV或其他任何内容的代码。使用该片段的最终用户可能不知道它的工作原理,并且可能在自己的代码中调用类似$('div').doSomething()的东西,因此也会在片段添加的DIV上调用。同样,如果我的页面中有3个DIV,我希望document.getElementsByTagName('div')返回3个项目而不是4个。 - Marco Demaio
1
创建的 div 并没有添加到 DOM 中,只是使用 document.createElement 创建并在函数返回后被丢弃(因为它只被分配给一个局部变量)。我刚刚在函数执行后测试了 document.getElementsByTagName('div').length(在 IE 和 Firefox 中),它返回了我的文档中 div 的正确数量。 - Marcel Korpel
1
这个不再起作用了。IE10不再支持条件注释。 - axelvnk
显示剩余3条评论
15个回答

58

James Padolsey在GitHub上放了一个小片段,我在这里引用:

// ----------------------------------------------------------
// A short snippet for detecting versions of IE in JavaScript
// without resorting to user-agent sniffing
// ----------------------------------------------------------
// If you're not in IE (or IE version is less than 5) then:
// ie === undefined
// If you're in IE (>=5) then you can determine which version:
// ie === 7; // IE7
// Thus, to detect IE:
// if (ie) {}
// And to detect the version:
// ie === 6 // IE6
// ie > 7 // IE8, IE9 ...
// ie < 9 // Anything less than IE9
// ----------------------------------------------------------

// UPDATE: Now using Live NodeList idea from @jdalton

var ie = (function(){

    var undef,
        v = 3,
        div = document.createElement('div'),
        all = div.getElementsByTagName('i');

    while (
        div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->',
        all[0]
    );

    return v > 4 ? v : undef;

}());

当然,所有的功劳都应该归给詹姆斯,我只是个传话者(但如果我的复制粘贴出了错,请射杀我这个传话者)。
另外,看看被创建的分支。保罗·爱尔兰在评论中解释了内部工作原理。

12
IE10不再支持条件语句(Conditional statements)。 - rds
HTML 中只有条件注释不再被支持(例如 <!--[if IE]><![endif]-->),而不是IE10中的条件语句。 - Qantas 94 Heavy
我喜欢这个函数,因此我创建了一个版本,可以在IE10中运行,并以相同的方式调用,这样任何其他使用它的人都可以只需放入替换即可。 - Sean Colombo

39

如果你希望以这种方式实现,我认为最好使用条件编译,因为你可以在javascript内部完成操作而不需要改变HTML:

var isIE = /*@cc_on!@*/false;

7
@AlfonsoML 这是什么奇怪的黑客攻击? :) - Šime Vidas
20
请记住,压缩器不喜欢这种东西;YUI Compressor 会生气,Google Closure Compiler 会出问题。 - Marcel Korpel
2
这个可以工作。然而,与条件注释不同的是,使用条件编译无法区分IE的版本,只能区分不同版本的JScript引擎(它们可以独立于IE版本进行交换和替换)。 - Tim Down
5
多年来,我一直在阅读有关条件注释和userAgent字符串的内容,而现在你告诉我只需要这一行代码就可以检测IE? :p - Šime Vidas
4
我在Windows 7和8上尝试在IE10上运行它,但它没有起作用。 - Ritesh
显示剩余12条评论

26

Marcel Korpel的答案已不再适用(在IE 10中返回undef,因此IE 10似乎不是IE)。注意:现已更新以与IE11一起使用。

这是该代码的一个变体,来自于Microsoft的建议。如果您之前使用的是旧代码,可以直接放入此替换内容,因为其调用方式完全相同。

与条件注释/编译不同,它也应该可以与缩小器一起正常工作。

// ----------------------------------------------------------
// If you're not in IE (or IE version is less than 5) then:
// ie === undefined
// If you're in IE (>=5) then you can determine which version:
// ie === 7; // IE7
// Thus, to detect IE:
// if (ie) {}
// And to detect the version:
// ie === 6 // IE6
// ie > 7 // IE8, IE9, IE10 ...
// ie < 9 // Anything less than IE9
// ----------------------------------------------------------
var ie = (function(){
    var undef,rv = -1; // Return value assumes failure.
    var ua = window.navigator.userAgent;
    var msie = ua.indexOf('MSIE ');
    var trident = ua.indexOf('Trident/');

    if (msie > 0) {
        // IE 10 or older => return version number
        rv = parseInt(ua.substring(msie + 5, ua.indexOf('.', msie)), 10);
    } else if (trident > 0) {
        // IE 11 (or newer) => return version number
        var rvNum = ua.indexOf('rv:');
        rv = parseInt(ua.substring(rvNum + 3, ua.indexOf('.', rvNum)), 10);
    }

    return ((rv > -1) ? rv : undef);
}());

更新以兼容IE11。感谢“acarlon”指出它没有工作,“mario”提供的代码是我修复的基础!


2
但这种方法是通过 User-Agent 字符串嗅探实现的;UA 字符串很容易被欺骗,但条件注释则不会。反正,谁需要检测 IE 10 呢?现在你可以使用特性检测来测试所有东西,这远比浏览器检测更可取(浏览器检测只用于检测无法使用特性检测检测到的内容)。 - Marcel Korpel
1
这对我很有帮助,因为我需要特别检测IE 10。 - user396070
2
@Marcel 如果你想要假扮成别人,随意。这是为了帮助那些普通的IE白痴(不会做欺骗)而设计的。如果你想要伪装,那只会伤害到你自己(可能)。 - bjb568
2
这在IE11上不再起作用,因为navigator.appName不是M$。但是这个答案有效:https://dev59.com/MGIj5IYBdhLWcg3wrG8q#21712356 - acarlon
1
谢谢,@SeanColombo。它很丑,但它可以工作。 - JMD
显示剩余2条评论

11

IE 11发生了很多改变,现在许多过去的浏览器检测方法不起作用了。下面的代码适用于IE 11及更早版本。

function isIE()
{
    var isIE11 = navigator.userAgent.indexOf(".NET CLR") > -1;      
    var isIE11orLess = isIE11 || navigator.appVersion.indexOf("MSIE") != -1;
    return isIE11orLess;
}

这看起来非常不错,但为什么你使用“.NET CLR”而不是“Trident”? - Lightningsoul
谢谢,我正在使用这个来alert()然后将IE用户重定向到http://browsehappy.com/ :) 对于一个个人的Web应用程序,另一个Steam库:http://sam.nipl.net/free-games.html 我现在不想经历让它在IE中工作的痛苦! - Sam Watkins
@Ligntningsoul:搜索“.NET CLR”强调了这是一项微软技术,并且在不久的将来不太可能改变。 - webber55
1
这是到目前为止我最喜欢的答案。它有效且简洁。感谢@webber55。 - Trev14

6
我认为我有你需要的东西。你可以使用Javascript和clientCaps获取Internet Explorer的完整版本号,格式为“AA.BB.CCCC.DDDD”。 http://www.pinlady.net/PluginDetect/IE/ 它似乎适用于IE 5.5及更高版本(包括IE 10)。它不受navigator.userAgent/document mode/browser mode的影响。没有必要使用条件注释或任何额外的HTML元素,这是一个纯Javascript解决方案。
目前我还不确定IE Mobile的行为如何,但如果clientCaps方法失败,你可以始终使用备用检测方法。
到目前为止,我必须说,它工作得相当不错。

4

我认为你已经回答了自己的问题:首先,它只能检测IE浏览器,因此这个脚本实际上将浏览器分成了两部分:IE和<everythingelse>。

其次,你需要在每个HTML页面添加一个奇怪的注释。鉴于广泛使用的JavaScript库(如jQuery和YUI)必须“易于”插入/利用各种网站,你会自动使它们更难以使用。


3

navigator.userAgent存在,如果需要进行浏览器检测(而不是特性检测),jQuery使用它来获取$.browser对象的信息。这比在每个页面中包含IE特定的条件注释要好得多。


3
浏览器可以伪造它们的userAgent字符串,但有条件的注释只在IE中执行,没有例外。 - Šime Vidas
1
@Šime Vidas:确实如此,虽然我想知道有多少用户正在伪造他们的用户代理字符串? - PleaseStand
@Marco 用户也可以。例如,我伪造了iPhone的字符串,以便在我的桌面浏览器上查看iPhone版本的网页 :) - Šime Vidas
@Sime Vidas:有趣,这是更多避免使用userAgent的原因。 - Marco Demaio
2
@ŠimeVidas 难道这不是使用用户代理的原因吗?如果用户希望页面看起来像IE,那么就让他们将User-Agent设置为某个IE。如果您想测试移动站点,则应该响应iPhone用户代理。 - Cobby
显示剩余2条评论

2

2

2

我正在使用以下代码:

var isIE = navigator.userAgent.indexOf(' MSIE ') > -1;

这段代码判断当前浏览器是否为IE浏览器。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接