Javascript IE 检测,为啥不使用简单的条件注释? [复制]

Posted

技术标签:

【中文标题】Javascript IE 检测,为啥不使用简单的条件注释? [复制]【英文标题】:Javascript IE detection, why not use simple conditional comments? [duplicate]Javascript IE 检测,为什么不使用简单的条件注释? [复制] 【发布时间】:2011-05-09 07:45:24 【问题描述】:

为了检测 IE,大多数 javascript 库都会使用各种技巧。

jQuery 似乎在页面的 DOM 中添加了一个临时对象以检测某些功能, YUI2 在其YAHOO.env.ua = function()(文件yahoo.js)中对用户代理执行正则表达式

在阅读this answer 之后,我认为这是真的,为了检测 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)
   ...

除了因为必须在所有页面中添加它可能会导致痛苦之外,还有什么我可能不知道的问题/注意事项吗?


仅供参考:我知道使用object detection rather than browser detection 会更好,但在某些情况下您仍然必须使用浏览器检测。

【问题讨论】:

JS 库尝试使用 JavaScript 而不是条件 cmets 检测 IE 的一个主要原因是,对于条件 cmets,您需要向页面添加另一个脚本(这个脚本甚至看起来很奇怪)。这可能会让一些人(新程序员)感到困惑或惹恼其他人。 您忘记关闭条件注释中的 SCRIPT 元素... 在一个完美的世界中,您将只有两组 JavaScript 引擎作为目标,IE 和所有其他引擎。我们并不生活在那个世界。没关系,在一个完美的世界里,你只有一个引擎,所有这些都是废话。 (我的意思是,您通常需要的不仅仅是 if !ie) 创建的 div 并没有添加到 DOM 中,仅使用 document.createElement 创建并在函数返回后丢弃(因为它仅分配给局部变量)。我刚刚在函数执行后(在 IE 和 Firefox 中)测试了document.getElementsByTagName('div').length,它在我的文档中返回了正确数量的 div。 这不再起作用了。 IE10 不再支持条件 cmets 【参考方案1】:

你为什么不直接用 html5 编程,然后检查一下

if ( window.navigator.product !== "Gecko" )

??诚然,这将在“Gecko”系列中包含 IE11,但它现在不应该足够好吗?

注意:HTML5 规范。表示 navigator.product 必须返回“Gecko”...而 IE10 及更早版本都返回其他内容。

【讨论】:

developer.mozilla.org/en-US/docs/Web/API/NavigatorID.product 已弃用的功能,也从未用于功能/浏览器检测。 IE 11 在其他浏览器似乎运行良好时仍然会中断。我今天正在做一些 jQuery 淡入淡出和内容交换,而 IE 11 是唯一一个决定不工作的。【参考方案2】:

对于我的用例,我真的只需要检测是否低于IE9,所以我使用

if (document.body.style.backgroundSize === undefined && navigator.userAgent.indexOf('MSIE') > -1)

//IE8- stuff

【讨论】:

【参考方案3】:

Marcel Korpel 的回答不再有效(在 IE 10 中它返回 undef,因此 IE 10 看起来不是 IE)。注意:现在更新后也可以与 IE 11 一起使用。

这是该代码的变体,但来自Microsoft's recommendations。如果您使用的是以前的代码,则可以直接替换,因为它的调用方式完全相同。

与条件 cmets/compilation 不同,它也可以与最小化器一起正常工作。

// ----------------------------------------------------------
// 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' 提供我修复的代码!

【讨论】:

但这适用于用户代理字符串嗅探; UA 字符串很容易被欺骗,但条件 cmets 不能。无论如何,谁需要检测 IE 10?您现在可以使用特征检测来测试所有内容,这远远优于浏览器检测(仅需要检测特征检测无法检测到的事物)。 @MarcelKorpel:“if(ie)”在 IE 10 中返回 false 是非常具有误导性的,因为它 IE。关于欺骗,这是真的。我认为在大多数情况下(除了与安全相关的问题之外的所有情况),如果用户想要欺骗用户代理,那么响应他们选择代表自己的 UA 就可以了。在我的特定用例中,我正在与 Trello 的 API 交互,其“弹出”身份验证目前在任何版本的 IE(包括 IE10)中都不起作用,所以如果(即),我选择使用不同的方法(使用更少最佳的 UI,但至少它在 IE 中有效)。 这对我有帮助,因为我特别需要检测 IE 10。 @Marcel 如果您想假装成其他人,请随意。这应该可以帮助普通的 IE 白痴(他们不会进行欺骗)。如果你想假装,那不会伤害任何人,除了(可能)你自己。 这不再适用于 IE11,因为 navigator.appName 不是 M$。这个答案虽然有效:***.com/a/21712356/746754【参考方案4】:

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”呢? 谢谢,我正在使用它来 alert() 然后将 IE 用户重定向到 browsehappy.com :) 对于个人网络应用程序,另一个 Steam 库:sam.nipl.net/free-games.html 我不想去通过现在让它在 IE 中工作的痛苦! @Ligntningsoul:搜索“.NET CLR”强调这是一项微软技术,近期内不太可能改变。 这是迄今为止我最喜欢的答案。它有效且简洁。谢谢@webber55【参考方案5】:
var version = navigator.userAgent.match(/(msie) (\d+)/i);
console.log(version);

看了这个问题后我很快就写了一些东西,以防有人想要它。

** 编辑 **

根据以下 Johnny Darvall 的评论,我正在为任何试图嗅探 Internet Explorer 11 的人添加一个链接:: p>

http://blogs.msdn.com/b/ieinternals/archive/2013/09/21/internet-explorer-11-user-agent-string-ua-string-sniffing-compatibility-with-gecko-webkit.aspx

【讨论】:

也为我工作。谢谢【参考方案6】:

我正在使用该代码

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

【讨论】:

【参考方案7】:

您可以在这里找到一些非常简单的浏览器检测技巧:http://www.thespanner.co.uk/2009/01/29/detecting-browsers-javascript-hacks/

var isIE = IE='\v'=='v';

【讨论】:

【参考方案8】:

我想我有你要找的东西。您可以使用 Javascript 和 clientCaps 以字符串“AA.BB.CCCC.DDDD”的形式获取 Internet Explorer 的完整版本。

http://www.pinlady.net/PluginDetect/IE/

它似乎适用于 IE 5.5 及更高版本(包括 IE 10)。 它不受 navigator.userAgent/document 模式/browser 模式的影响。 不需要条件 cmets 或任何额外的 HTML 元素。这是一个纯 Javascript 解决方案。

目前我不确定 IE Mobile 的行为如何,但您始终可以使用备份检测方法以防此 clientCaps 方法失败。

到目前为止,我得说,它运作良好。

【讨论】:

【参考方案9】:

这很好用,var isIe = !!window.ActiveXObject;

【讨论】:

不知道IE9能不能用。引用 MSDN:“在 Internet Explorer 9 之前的 Internet Explorer 版本中,一些 Web 作者使用 window.ActiveXObject 来提供特定于 Internet Explorer 的内容。强烈不鼓励这种做法。” [参考。 msdn.microsoft.com/en-us/library/ff974676(v=VS.85).aspx]【参考方案10】:

James Padolsey 写了一个little snippet on 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;

());

当然,所有的功劳都应该归詹姆斯所有,我只是信使(但如果我的复制粘贴操作出错,请开除信使)。

还请查看已创建的分叉。 Paul Irish 在comment 中解释了内部工作原理。

【讨论】:

条件语句为not supported on IE10 any more。 不再支持 HTML 中的条件 cmets(例如 &lt;!--[if IE]&gt;&lt;![endif]--&gt;),IE10 中不支持条件语句。 我喜欢这个功能,所以我创建了一个在 IE10 下工作的版本,并且调用方式相同,因此任何其他使用它的人都可以直接替换。【参考方案11】: 它污染了全局命名空间 它需要更改两个文件。 它只适用于 IE 从技术上讲,条件注释仍然是注释

【讨论】:

Point 1) 它不会污染全局命名空间,我在窗口对象中使用它。第 3 点)注意它适用于任何浏览器,如果条件在其他浏览器上返回 false,它不会中断,我只是在检查对象属性。 @Marco window['isIE'] = true;var isIE = true; 基本相同(在全局代码中),因为window 指向全局对象。但是,使用一个全局属性来检测 IE 没什么大不了的。 1) “window”是全局对象。 3) 对。我的意思是说条件 cmets 仅在 IE 中有效。 嗯,这就是 OP 想要的。他希望它们在 IE 中执行,而在其他浏览器中被忽略。【参考方案12】:

我想你回答了你自己的问题:首先,它只检测 IE,所以脚本本质上会将浏览器的世界分成两部分:IE 和

其次,您必须为每个 HTML 页面添加一个看起来很古怪的评论。鉴于 jQuery 和 YUI 等范围广泛的 JavaScript 库必须“易于”插入/用于广泛的网站,您会自然而然地使它们更难使用。

【讨论】:

【参考方案13】:

检查浏览器是个坏主意 - 最好改为检查浏览器的功能。例如,通常您检查用户是否正在使用 IE,因为您想使用 IE 不支持的某些功能。但是,您知道所有当前和未来的非 IE 浏览器都将支持该功能吗?不。 所以方式例如jQuery 使用更好:它创建并执行小测试用例检查某些错误/功能 - 您可以简单地检查 if(browser_supports_XYZ) 之类的东西,而不是检查用户是否使用特定的浏览器。

无论如何,总有一些情况需要检查浏览器,因为这是一个视觉错误,您无法使用脚本进行测试。在这种情况下,最好使用 javascript 而不是条件 cmets,因为您可以让浏览器在您需要它的位置而不是在其他地方进行检查(想象一个 .js 文件,您可以在其中检查 isIE 从未在该文件中定义)

【讨论】:

我没有给你-1,但我无法对给你的人微笑。阅读我的问题的底部。 您建议运行什么测试来检测浏览器是否支持 .png 中的 alpha 甚至更好的 .gifs。 听起来像“goto 被认为是有害的”。我需要检查 IE,所以我可以重定向这些人以获得更好的浏览器;) 有些东西是你无法检测到的,比如浏览器如何处理来自按钮触发器的多个文件下载。对于其他一切,还有特征检测【参考方案14】:

如果您想这样做,我认为使用条件编译会更好,因为您可以在 javascript 中执行此操作而无需更改 html:

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

【讨论】:

@AlfonsoML 这是什么奇怪的黑客行为? :) 请记住,缩小器不喜欢这样的想法; YUI Compressor 生气了,Google Closure Compiler 窒息。 这行得通。但是,与条件 cmets 不同,条件编译无法区分 IE 的版本,只能区分 JScript 引擎的不同版本(可以独立于 IE 版本进行交换和替换)。 @AlfonsoML 多年来,我一直在阅读有关条件 cmets 和 userAgent 字符串的信息,现在您告诉我您可以用这一行检测 IE? :p 我在 Windows 7 和 8 的 IE10 上尝试过,但没有成功。【参考方案15】:

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

【讨论】:

浏览器可以伪造他们的 userAgent 字符串,但条件 cmets 只能在 IE 中执行,无一例外。 @Šime Vidas:是的,虽然我想知道:有多少用户在伪造他们的用户代理字符串? @Sime Vidas:不是用户,而是 Trident(IE 引擎)可能用于许多不完全是 IE(可能是移动设备)的浏览器,并且浏览器会多次伪造 userAgent 字符串以假装是 IE或类似的,这就是为什么在可能的情况下对象检测比浏览器检测更好。 @Marco 用户也是如此。例如,我伪造了 iPhone 字符串,以便能够在我的桌面浏览器上查看 iPhone 版本的网页 :) @ŠimeVidas 这不是使用用户代理的理由吗?如果用户希望页面看起来像 IE,那么让他们将 User-Agent 设置为 IE。如果你想测试一个移动网站,它应该响应一个 iPhone 用户代理。

以上是关于Javascript IE 检测,为啥不使用简单的条件注释? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

javascript 在 mozilla 中运行良好,但在 IE6 中出现未知的运行时错误,为啥?

在 JavaScript 中检测 IE 版本(v9 之前)

为啥 JavaScript 只有在 IE 中打开开发者工具一次后才能工作?

如何在 Asp.net 中使用 javascript 检测 IE 11

如何使用 JavaScript 检测 Internet Explorer (IE) 和 Microsoft Edge?

IE6 不喜欢我的简单 jQuery:知道为啥吗?