如何检测Safari、Chrome、IE、Firefox和Opera浏览器?

1079

我有5个适用于Firefox、Chrome、Internet Explorer(IE)、Opera和Safari的插件/扩展程序。

当用户单击“安装”按钮后,如何正确识别用户的浏览器并重定向到下载相应的插件?


4
尝试使用DetectJS,它可以用于所有浏览器。 - dude
1
可能是JavaScript中的浏览器检测?的重复问题。 - Matthijs Wessels
3
detect.js已不再维护(根据https://github.com/darcyclarke/Detect.js),他们推荐使用https://github.com/lancedikson/bowser。 - YakovL
1
可能是重复的问题:如何检测浏览器的版本? - KyleMit
4
我想重新提出这个问题 - 现在是否有可靠且简单的答案了?在SO上有很多(旧的)类似问题,但大多都是基于“userAgent”函数,即使w3schools也承认它不准确。我已经测试过一些回答这个问题和类似问题的答案,但没有一个看起来可靠。如果我最好另外发一个新的问题,请告诉我。 - AutoBaker
显示剩余3条评论
30个回答

2001
当你搜索浏览器可靠检测时,通常会得到检查用户代理字符串的结果。这种方法是不可靠的,因为很容易伪造该值。
我编写了一种通过鸭子类型来检测浏览器的方法。
只有在真正需要时才使用浏览器检测方法,比如显示特定于浏览器的指令以安装扩展程序。尽可能使用功能检测。
演示:https://jsfiddle.net/6spj1059/

// Opera 8.0+
var isOpera = (!!window.opr && !!opr.addons) || !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;

// Firefox 1.0+
var isFirefox = typeof InstallTrigger !== 'undefined';

// Safari 3.0+ "[object HTMLElementConstructor]" 
var isSafari = /constructor/i.test(window.HTMLElement) || (function (p) { return p.toString() === "[object SafariRemoteNotification]"; })(!window['safari'] || (typeof safari !== 'undefined' && window['safari'].pushNotification));

// Internet Explorer 6-11
var isIE = /*@cc_on!@*/false || !!document.documentMode;

// Edge 20+
var isEdge = !isIE && !!window.StyleMedia;

// Chrome 1 - 79
var isChrome = !!window.chrome && (!!window.chrome.webstore || !!window.chrome.runtime);

// Edge (based on chromium) detection
var isEdgeChromium = isChrome && (navigator.userAgent.indexOf("Edg") != -1);

// Blink engine detection
var isBlink = (isChrome || isOpera) && !!window.CSS;


var output = 'Detecting browsers by ducktyping:<hr>';
output += 'isFirefox: ' + isFirefox + '<br>';
output += 'isChrome: ' + isChrome + '<br>';
output += 'isSafari: ' + isSafari + '<br>';
output += 'isOpera: ' + isOpera + '<br>';
output += 'isIE: ' + isIE + '<br>';
output += 'isEdge: ' + isEdge + '<br>';
output += 'isEdgeChromium: ' + isEdgeChromium + '<br>';
output += 'isBlink: ' + isBlink + '<br>';
document.body.innerHTML = output;

可靠性分析

先前的方法依赖于渲染引擎的属性(-moz-box-sizing-webkit-transform)来检测浏览器。这些前缀最终会被弃用,因此为了使检测更加稳健,我转而使用浏览器特定的特征:

  • Internet Explorer: JScript的条件编译(在IE9之前)和document.documentMode
  • Edge: 在Trident和Edge浏览器中,微软的实现公开了StyleMedia构造函数。排除Trident后我们得到Edge。
  • Edge(基于Chromium):用户代理在结尾处包括值“Edg / [version]”(例如:“Mozilla / 5.0(Windows NT 10.0; Win64; x64)AppleWebKit / 537.36(KHTML, like Gecko)Chrome / 80.0.3987.16 Safari / 537.36 Edg / 80.0.361.9 ”)。
  • Firefox:Firefox的API安装附加组件:InstallTrigger
  • Chrome:全局chrome对象,包含多个属性,包括文档化的chrome.webstore对象。
  • 更新3 chrome.webstore已弃用并在最新版本中未定义
  • Safari:其构造函数命名中的独特模式。这是所有列出的属性中最不耐久的方法,你知道吗?在Safari 9.1.3中修复了这个问题。因此,我们正在检查SafariRemoteNotification,它在版本7.1之后引入,以覆盖从3.0及以上的所有Safari。
  • Opera:window.opera已存在多年,但是当Opera将其引擎替换为Blink + V8(由Chromium使用)时,将被删除
  • 更新1:Opera 15已发布,其UA字符串看起来像Chrome,但添加了“OPR”。在此版本中,定义了chrome对象(但未定义chrome.webstore)。由于Opera努力克隆Chrome,因此我使用用户代理嗅探来实现此目的。
  • 更新2:!!window.opr && opr.addons可用于检测Opera 20+(常青)。
  • Blink:CSS.supports()在Google切换Chrome 28时引入Blink。当然,这与Opera中使用的相同Blink。

已成功测试于:

  • Firefox 0.8 - 61
  • Chrome 1.0 - 71
  • Opera 8.0 - 34
  • Safari 3.0 - 10
  • IE 6 - 11
  • Edge - 20-42
  • Edge Dev - 80.0.361.9

更新于2016年11月,包括检测Safari浏览器版本9.1.3及以上

更新于2018年8月,更新了对chrome、firefox、IE和edge的最新成功测试。

更新于2019年1月,修复了chrome检测问题(因为window.chrome.webstore已被弃用),并包含chrome的最新成功测试。

更新于2019年12月,添加基于Chromium的Edge浏览器检测(基于@Nimesh评论)。


9
FYI,这在Chrome扩展中不起作用,因为那里window.chrome.webstore未定义。尚未使用Firefox扩展进行检查。在其他地方提到的is.js可以在Chrome和Firefox扩展中使用。 - nevf
83
isSafari 在 Safari 10 中无法使用。我认为这是一个不好的解决方案(虽然我没有更好的解决方案)。不能保证你检查的许多东西不会被其他浏览器删除或添加。所有使用此代码来检查 Safari 的网站在升级到 macOS Sierra 或 Safari 10 后都将出现问题 :( - gman
13
这个在桌面版本上测试过了,那么移动版本的浏览器呢?不同平台有不同的移动版本和桌面版本。因此,Firefox 在 Windows、Linux 和 Mac OS 上有 3 个二进制版本,在 Android 和 iOS 上有 2 个二进制版本。 - DrZ214
5
当前的 isSafari 在 Safari 10.1.2 的 <iframe> 下无法工作。 - Mikko Ohtamaa
36
从 Chrome 版本 71 开始,window.chrome.webstore 已被弃用:https://blog.chromium.org/2018/06/improving-extension-transparency-for.html。 - st_bk
显示剩余72条评论

204

你可以尝试以下方法来检查浏览器版本。

    <!DOCTYPE html>
    <html>
    <body>
    <p>What is the name(s) of your browser?</p>
    <button onclick="myFunction()">Try it</button>
    <p id="demo"></p>
    <script>
    
    function myFunction() { 
     if((navigator.userAgent.indexOf("Opera") || navigator.userAgent.indexOf('OPR')) != -1 ) 
    {
        alert('Opera');
    }
    else if(navigator.userAgent.indexOf("Edg") != -1 )
    {
        alert('Edge');
    }
    else if(navigator.userAgent.indexOf("Chrome") != -1 )
    {
        alert('Chrome');
    }
    else if(navigator.userAgent.indexOf("Safari") != -1)
    {
        alert('Safari');
    }
    else if(navigator.userAgent.indexOf("Firefox") != -1 ) 
    {
         alert('Firefox');
    }
    else if((navigator.userAgent.indexOf("MSIE") != -1 ) || (!!document.documentMode == true )) //IF IE > 10
    {
      alert('IE'); 
    }  
    else 
    {
       alert('unknown');
    }
    }
    </script>
    
    </body>
    </html>

如果你只需要知道IE浏览器的版本,可以按照下面的代码进行操作。此代码适用于IE6到IE11版本。

<!DOCTYPE html>
<html>
<body>

<p>Click on Try button to check IE Browser version.</p>

<button onclick="getInternetExplorerVersion()">Try it</button>

<p id="demo"></p>

<script>
function getInternetExplorerVersion() {
   var ua = window.navigator.userAgent;
        var msie = ua.indexOf("MSIE ");
        var rv = -1;

        if (msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./))      // If Internet Explorer, return version number
        {               

            if (isNaN(parseInt(ua.substring(msie + 5, ua.indexOf(".", msie))))) {
                //For IE 11 >
                if (navigator.appName == 'Netscape') {
                    var ua = navigator.userAgent;
                    var re = new RegExp("Trident/.*rv:([0-9]{1,}[\.0-9]{0,})");
                    if (re.exec(ua) != null) {
                        rv = parseFloat(RegExp.$1);
                        alert(rv);
                    }
                }
                else {
                    alert('otherbrowser');
                }
            }
            else {
                //For < IE11
                alert(parseInt(ua.substring(msie + 5, ua.indexOf(".", msie))));
            }
            return false;
        }}
</script>

</body>
</html>

5
为什么要写这么多行代码?userAgent 是含糊不清的。 - igauravsehrawat
7
微软Edge怎么样? - user6031759
4
上面的答案在检查 Safari 之前先检查 Chrome,因为 Safari 在用户代理中没有 chrome 关键词。例如 Safari 的用户代理:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5) AppleWebKit/601.6.17 (KHTML, like Gecko) Version/9.1.1 Safari/601.6.17 - Golak Sarangi
28
Stackoverflow使用这种方法。 - vityavv
7
在使用 Opera 浏览器(最新版本)测试时,这段代码返回的是 'Chrome'。为了解决这个问题,我将 Opera 的条件语句更改为:if(navigator.userAgent.indexOf("Opera") != -1 || navigator.userAgent.indexOf('OPR') != -1 ) - Kyle Vassella
显示剩余16条评论

80

以下是2019年12月的几个处理浏览器检测的著名库。

Bowser by lancedikson - 4,065★s - 最后更新于2019年10月2日 - 4.8KB

var result = bowser.getParser(window.navigator.userAgent);
console.log(result);
document.write("You are using " + result.parsedResult.browser.name +
               " v" + result.parsedResult.browser.version + 
               " on " + result.parsedResult.os.name);
<script src="https://unpkg.com/bowser@2.7.0/es5.js"></script>

*支持基于Chromium的Edge浏览器


bestiejs的Platform.js - 2,550颗星 - 最后更新于2019年4月14日 - 5.9KB

console.log(platform);
document.write("You are using " + platform.name +
               " v" + platform.version + 
               " on " + platform.os);
<script src="https://cdnjs.cloudflare.com/ajax/libs/platform/1.3.5/platform.min.js"></script>

jQuery Browser 是由 gabceb 开发的插件,获得了 504 个星标,最后更新于2015年11月23日,文件大小为 1.3KB。

console.log($.browser)
document.write("You are using " + $.browser.name +
               " v" + $.browser.versionNumber + 
               " on " + $.browser.platform);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-browser/0.1.0/jquery.browser.min.js"></script>

检测.js(已存档)由darcyclarke创建- 522★s-最后更新于2015年10月26日-2.9KB

var result = detect.parse(navigator.userAgent);
console.log(result);
document.write("You are using " + result.browser.family +
               " v" + result.browser.version + 
               " on " + result.os.family);
<script src="https://cdnjs.cloudflare.com/ajax/libs/Detect.js/2.2.2/detect.min.js"></script>

浏览器检测(归档),作者 QuirksMode - 最后更新于 2013 年 11 月 14 日 - 884 字节

console.log(BrowserDetect)
document.write("You are using " + BrowserDetect.browser +
               " v" + BrowserDetect.version + 
               " on " + BrowserDetect.OS);
<script src="https://kylemit.github.io/libraries/libraries/BrowserDetect.js"></script>

值得一提的是:

  • WhichBrowser - 1,355星 - 最近更新于2018年10月2日
  • Modernizr - 23,397星 - 最近更新于2019年1月12日 - 要喂饱已经饱了的马,功能检测应该支持任何canIuse风格的问题。浏览器检测真的只是为了提供定制的图像、下载文件或针对个别浏览器的说明。

进一步阅读


4
不必重复造轮子,哪怕增加一些 Kb 的开销也是值得的。 - 111

71

我知道为此使用一个库可能过于冗长,但只是为了丰富这个话题,你可以查看is.js的做法:

is.firefox();
is.ie(6);
is.not.safari();

14
值得注意的是,在底层它主要进行用户代理检测,有时也会在某些地方辅以供应商检测和一些特性检测。 - TygerKrash
1
@TygerKrash 当然,你说得对。这实际上就是我在回答中所指的:打开is.js的源代码并查看他们是如何做到的。 - Rafael Eyng
4
jQuery曾经包括类似的属性:$.browser.msie...但在1.9版本中已经被移除。http://api.jquery.com/jquery.browser/ - Ricardo stands with Ukraine
@RafaelEyng:我认为它进行用户代理检测的问题在于这种方法不可靠。 - HoldOffHunger
1
这绝对是最强劲的方法,当您假定UA字符串未被修改时。它还能正确检测操作系统(android, win, mac, linux);设备类型(桌面、平板电脑、移动设备)。它还可以测试浏览器的版本。 - kashiraja
is.js Bug: is.Chrome()在所有iOS设备上的Google Chrome中返回false。MacOS上的Chrome正常运行。 - akcasoy

50

短变量 (2020年7月10日更新移动浏览器检测修复)

var browser = (function() {
    var test = function(regexp) {return regexp.test(window.navigator.userAgent)}
    switch (true) {
        case test(/edg/i): return "Microsoft Edge";
        case test(/trident/i): return "Microsoft Internet Explorer";
        case test(/firefox|fxios/i): return "Mozilla Firefox";
        case test(/opr\//i): return "Opera";
        case test(/ucbrowser/i): return "UC Browser";
        case test(/samsungbrowser/i): return "Samsung Browser";
        case test(/chrome|chromium|crios/i): return "Google Chrome";
        case test(/safari/i): return "Apple Safari";
        default: return "Other";
    }
})();
console.log(browser)

Typescript 版本:

export enum BROWSER_ENUM {
  EDGE ,
  INTERNET_EXPLORER ,
  FIRE_FOX ,
  OPERA ,
  UC_BROWSER ,
  SAMSUNG_BROWSER ,
  CHROME ,
  SAFARI ,
  UNKNOWN ,
}

const testUserAgent = (regexp: RegExp): boolean => regexp.test(window.navigator.userAgent);

function detectBrowser(): BROWSER_ENUM {
  switch (true) {
    case testUserAgent(/edg/i): return BROWSER_ENUM.EDGE;
    case testUserAgent(/trident/i): return BROWSER_ENUM.INTERNET_EXPLORER;
    case testUserAgent(/firefox|fxios/i): return BROWSER_ENUM.FIRE_FOX;
    case testUserAgent(/opr\//i): return BROWSER_ENUM.OPERA;
    case testUserAgent(/ucbrowser/i): return BROWSER_ENUM.UC_BROWSER;
    case testUserAgent(/samsungbrowser/i): return BROWSER_ENUM.SAMSUNG_BROWSER;
    case testUserAgent(/chrome|chromium|crios/i): return BROWSER_ENUM.CHROME;
    case testUserAgent(/safari/i): return BROWSER_ENUM.SAFARI;
    default: return BROWSER_ENUM.UNKNOWN;
  }
}

export const BROWSER: BROWSER_ENUM = detectBrowser();

export const IS_FIREFOX = BROWSER === BROWSER_ENUM.FIRE_FOX;

纯属娱乐的函数式算法:

 var BROWSER =  new Array(
     ["Microsoft Edge", /edg/i],
     ["Microsoft Internet Explorer", /trident/i],
     ["Mozilla Firefox", /firefox|fxios/i],
     ["Opera", /opr\//i],
     ["UC Browser", /ucbrowser/i],
     ["Samsung Browser", /samsungbrowser/i],
     ["Google Chrome", /chrome|chromium|crios/i],
     ["Apple Safari", /safari/i],
     ["Unknown", /.+/i],
 ).find(([, value]) => value.test(window.navigator.userAgent)).shift();

如果你不喜欢我,请解释一下原因。 - Alex Nikulin
5
在 iOS 上使用 Chrome 浏览时,将显示“Safari”。 - Reza
2
这种方法在桌面端的Chrome和Firefox以及iOS上的Safari中都有效。但是在iOS上的Chrome和Firefox中会失败。 - BReddy
这对我来说可行,因为我只针对Chrome、Edge、Firefox(稍后再考虑Safari)。但是目前它在所有浏览器上都可靠吗? - Gangula
1
@Gangula 目前在代码中可靠地支持所有浏览器,包括Microsoft Edge、Microsoft Internet Explorer、Opera、Firefox、Uc、Samsung、Chrome和Safari。 - Alex Nikulin
显示剩余4条评论

50

如果有人发现这个有用,我已经将Rob W的答案制成了一个函数,该函数返回浏览器字符串而不是让多个变量漂浮。由于浏览器也不能真正地在没有重新加载的情况下更改,因此我将其缓存结果以防止需要再次计算函数调用时的结果。

/**
 * Gets the browser name or returns an empty string if unknown. 
 * This function also caches the result to provide for any 
 * future calls this function has.
 *
 * @returns {string}
 */
var browser = function() {
    // Return cached result if avalible, else get result then cache it.
    if (browser.prototype._cachedResult)
        return browser.prototype._cachedResult;

    // Opera 8.0+
    var isOpera = (!!window.opr && !!opr.addons) || !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;

    // Firefox 1.0+
    var isFirefox = typeof InstallTrigger !== 'undefined';

    // Safari 3.0+ "[object HTMLElementConstructor]" 
    var isSafari = /constructor/i.test(window.HTMLElement) || (function (p) { return p.toString() === "[object SafariRemoteNotification]"; })(!window['safari'] || safari.pushNotification);

    // Internet Explorer 6-11
    var isIE = /*@cc_on!@*/false || !!document.documentMode;

    // Edge 20+
    var isEdge = !isIE && !!window.StyleMedia;

    // Chrome 1+
    var isChrome = !!window.chrome && !!window.chrome.webstore;

    // Blink engine detection
    var isBlink = (isChrome || isOpera) && !!window.CSS;

    return browser.prototype._cachedResult =
        isOpera ? 'Opera' :
        isFirefox ? 'Firefox' :
        isSafari ? 'Safari' :
        isChrome ? 'Chrome' :
        isIE ? 'IE' :
        isEdge ? 'Edge' :
        isBlink ? 'Blink' :
        "Don't know";
};

console.log(browser());


3
在 Edge 浏览器中,它返回 Chrome - Riz
3
@eFriend,我已更新答案以符合最新的浏览器测试。 - pilau
5
我喜欢这个,但我更希望使用userAgent()作为备选项,而不是显示“不知道”。 - HoldOffHunger
6
Chrome 71 已经移除了属性 window.chrome.webstore,因此这种方法不再可用。 - Bedla
1
我在Safari、Firefox和Chrome中尝试过,始终返回“不知道”。 - nightrain
显示剩余2条评论

14

我不知道这是否对任何人有用,但这是一个可以让TypeScript满意的变体:

export function getBrowser() {

 // Opera 8.0+
    if ((!!window["opr"] && !!["opr"]["addons"]) || !!window["opera"] || navigator.userAgent.indexOf(' OPR/') >= 0) {
        return 'opera';
    }

    // Firefox 1.0+
    if (typeof window["InstallTrigger"] !== 'undefined') {
        return 'firefox';
    }

    // Safari 3.0+ "[object HTMLElementConstructor]" 
    if (/constructor/i.test(window["HTMLElement"]) || (function(p) { return p.toString() === "[object SafariRemoteNotification]"; })(!window['safari'] || (typeof window["safari"] !== 'undefined' && window["safari"].pushNotification))) {
        return 'safari';
    }

    // Internet Explorer 6-11
    if (/*@cc_on!@*/false || !!document["documentMode"]) {
        return 'ie';
    }

    // Edge 20+
    if (!(/*@cc_on!@*/false || !!document["documentMode"]) && !!window["StyleMedia"]) {
        return 'edge';
    }

    // Chrome 1+
    if (!!window["chrome"] && !!window["chrome"].webstore) {
        return 'chrome';
    }

    // Blink engine detection
    if (((!!window["chrome"] && !!window["chrome"].webstore) || ((!!window["opr"] && !!["opr"]["addons"]) || !!window["opera"] || navigator.userAgent.indexOf(' OPR/') >= 0)) && !!window["CSS"]) {
        return 'blink';
    }
}

1
你为什么在一些if语句中使用“false”作为条件? - CodeMonkey
@YonatanNir 我认为它的目的是检测条件编译: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Microsoft_Extensions/at-cc-on - Lucas Azevedo
Typescript 会这样说:类型“{ new (): HTMLElement; prototype: HTMLElement; }”的参数不能赋给类型“string”的参数。 - Jorge Monroy

13

谢谢大家。我在最近的浏览器上测试了这里的代码片段:Chrome 55,Firefox 50,IE 11和Edge 38,并且我得出了以下适用于所有浏览器的组合。我相信它可以改进,但对于需要快速解决方案的人来说,这是一个不错的选择:

var browser_name = '';
isIE = /*@cc_on!@*/false || !!document.documentMode;
isEdge = !isIE && !!window.StyleMedia;
if(navigator.userAgent.indexOf("Chrome") != -1 && !isEdge)
{
    browser_name = 'chrome';
}
else if(navigator.userAgent.indexOf("Safari") != -1 && !isEdge)
{
    browser_name = 'safari';
}
else if(navigator.userAgent.indexOf("Firefox") != -1 ) 
{
    browser_name = 'firefox';
}
else if((navigator.userAgent.indexOf("MSIE") != -1 ) || (!!document.documentMode == true )) //IF IE > 10
{
    browser_name = 'ie';
}
else if(isEdge)
{
    browser_name = 'edge';
}
else 
{
   browser_name = 'other-browser';
}
$('html').addClass(browser_name);

它会向 HTML 添加一个 CSS 类,类名为浏览器的名称。


你在iOS上测试过Chrome吗? - Vic

12

以下是 Rob 在 2016 年做出的答案,已经更新了包括 Microsoft Edge 和 Blink 检测的部分。

(编辑:我已经使用这些信息更新了Rob在上面的回答。)

// Opera 8.0+ (UA detection to detect Blink/v8-powered Opera)
isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
// Firefox 1.0+
isFirefox = typeof InstallTrigger !== 'undefined';
// Safari 3.0+
isSafari = /constructor/i.test(window.HTMLElement) || (function (p) { return p.toString() === "[object SafariRemoteNotification]"; })(!window['safari'] || safari.pushNotification);
// Internet Explorer 6-11
isIE = /*@cc_on!@*/false || !!document.documentMode;
// Edge 20+
isEdge = !isIE && !!window.StyleMedia;
// Chrome 1+
isChrome = !!window.chrome && !!window.chrome.webstore;
// Blink engine detection
isBlink = (isChrome || isOpera) && !!window.CSS;

/* Results: */
console.log("isOpera", isOpera);
console.log("isFirefox", isFirefox);
console.log("isSafari", isSafari);
console.log("isIE", isIE);
console.log("isEdge", isEdge);
console.log("isChrome", isChrome);
console.log("isBlink", isBlink);

这种方法的美妙之处在于它依赖于浏览器引擎的属性,因此它甚至覆盖了派生浏览器,比如Yandex或Vivaldi,它们实际上与使用它们的引擎的主要浏览器兼容。唯一的例外是Opera,它依赖于用户代理嗅探,但是今天(即版本15及以上),甚至Opera本身也只是Blink的外壳。


1
@NoR 噢,你在使用虚拟机啊... MSAssertion 技巧已经调整到版本25了。但是因为很多开发者依赖于虚拟机,我会尝试将其调整到这个较旧的版本。明智之举。谢谢。 - pilau
1
@NoR 更新-应该是未来可靠的。StyleMedia(大写)对象特定于IE和Edge,并且似乎不会消失。 - pilau
@IssacGable,让我们修复它 - 哪个版本? - pilau
@pilau Safai 版本 10.1.2 (12603.3.8) - Issac Gable
1
我还发现UAParser是一个仍在维护的JS插件,非常准确且易于使用。 - Issac Gable
显示剩余4条评论

11
你可以使用 trycatch 来使用不同的浏览器错误消息。IE 和 Edge 混淆了,但我使用了 Rob W 的鸭子类型(基于这个项目:https://www.khanacademy.org/computer-programming/i-have-opera/2395080328)。
var getBrowser = function() {        
    try {
        var e;
        var f = e.width;
    } catch(e) {
        var err = e.toString();

        if(err.indexOf("not an object") !== -1) {
            return "safari";
        } else if(err.indexOf("Cannot read") !== -1) {
            return "chrome";
        } else if(err.indexOf("e is undefined") !== -1) {
            return "firefox";
        } else if(err.indexOf("Unable to get property 'width' of undefined or null reference") !== -1) {
            if(!(false || !!document.documentMode) && !!window.StyleMedia) {
                return "edge";
            } else {
                return "IE";
            }
        } else if(err.indexOf("cannot convert e into object") !== -1) {
            return "opera";
        } else {
            return undefined;
        }
    }
};

1
这是一个很好的想法:你既不需要“window”对象,也不需要“navigator”对象! - Vadim
我的建议是完全摆脱文档和窗口。请看IE代码块: return "firefox"; } else if(err.search("[object Error]") !== -1 && e.message != null && e.description != null){ return "IE"; } else if(err.search("cannot convert e into object") !== -1){ return "opera"; - Vadim
那有什么区别IE和Edge之间的区别吗? - Mason Jones
奇怪,我再也无法重现err.search("[object Error]")了。不管怎样,对我来说,Firefox与Chrome以及其他一些东西已经足够了。我在PAC文件中使用它,其中window和document对象不可用。 - Vadim
刚刚找到了原因。看起来在运行PAC文件时,Windows 7不使用我安装的IE11,而是使用类似于IE7的引擎(可能来自Windows主机)。因此,在那里使用err.toString()会返回"[object Error]",而在IE11中则会像您的代码一样返回"Unable to get property..."字符串。因此,上面的代码应该在IE7中失败。 - Vadim
在运行 Chrome 67 和 Opera 54 (OS X) 时,它们都返回相同的错误字符串 :( - brasofilo

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