【问题标题】: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

标签: javascript internet-explorer browser-detection conditional-comments


【解决方案1】:

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

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

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

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

【讨论】:

【解决方案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$。这个答案虽然有效:stackoverflow.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 用户代理。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-03-22
            • 2014-04-02
            • 2014-06-21
            • 1970-01-01
            • 2016-07-22
            • 2013-01-01
            相关资源
            最近更新 更多