Javascript ES6跨浏览器检测

我如何找到浏览器的Javascript引擎版本和支持ECMAScript 6?

我使用navigator.appVersion只是知道浏览器的版本,但不是引擎的版本。

特征检测

我建议您使用功能检测,而不是用启发式方法检测浏览器的引擎。要做到这一点,你可以简单地包装一些代码里面的try {..} catch(e){…}语句,或使用一些if(…)语句。

例如:

function check() {
    if (typeof SpecialObject == "undefined") return false;
    try { specialFunction(); }
    catch (e) { return false; }

    return true;
}

if (check()) {
    // Use SpecialObject and specialFunction
} else {
    // You cannot use them :(
}

为什么特征检测优于浏览器/引擎检测?

在大多数情况下,有多个原因使特征检测成为最佳选择:

>你不必依赖浏览器的版本,引擎或细节,也不能使用启发式方法来检测它们,这些方法很难实现。
>您不会陷入关于浏览器/引擎规格检测的错误。
>您不必担心浏览器特定的功能:例如WebKit浏览器有不同的规格比其他。
>您可以确定,一旦检测到功能,您就可以使用它。

这些是IMHO使特征检测成为最佳方法的主要原因。

功能检测后备

当使用特征检测时,当您不确定哪些特征可以/不能使用时,使用特征检测是一种非常聪明的方式,包括几个特征检测以及后续的更基本的方法(甚至从头开始创建这些方法),以防特征你想使用不支持。

使用回退的功能检测的一个简单示例可以应用于window.requestAnimationFrame功能,这不是所有浏览器都支持的,并且具有几个不同的前缀,具体取决于您正在处理的浏览器。在这种情况下,您可以轻松检测和回退,如下所示:

requestAnimationFrame = 
   window.requestAnimationFrame       // Standard name
|| window.webkitRequestAnimationFrame // Fallback to webkit- (old versions of Chrome or Safari)
|| window.mozRequestAnimationFrame    // Fallback to moz- (Mozilla Firefox)
|| false;                             // Feature not supported :(

// Same goes for cancelAnimationFrame
cancelAnimationFrame = window.cancelAnimationFrame || window.webkitCancelAnimationFrame || window.mozCancelAnimationFrame || false;

if (!requestAnimationFrame) {
    // Not supported? Build it by yourself!
    requestAnimationFrame = function(callback) {
        return setTimeout(callback, 0);
    }

    // No requestAnim. means no cancelAnim. Built that too.
    cancelAnimationFrame = function(id) {
        clearTimeout(id);
    }
}

// Now you can use requestAnimationFrame 
// No matter which browser you're running
var animationID = requestAnimationFrame(myBeautifulFunction);

ECMAScript 6(Harmony)特征检测

现在,来到真正的问题:如果你想检测对ES6的支持,你将无法像我上面所说的,因为相关的ES6功能的范围是基于新的语法和私人的话,并将抛出如果在ES5中使用SyntaxError,这意味着编写包含ES5和ES6的脚本是不可能的!

这里是一个例子来演示这个问题;下面的代码段将不工作,并且在执行前会被阻塞,因为包含非法语法。

function check() {
    "use strict";

    try { eval("var foo = (x)=>x+1"); }
    catch (e) { return false; }
    return true;
}

if (check()) {
    var bar = (arg) => { return arg; }
    // THIS LINE will always throw a SyntaxError in ES5
    // Even before checking for ES6
    // Because contains illegal syntax
} else {
    var bar = function(arg) { return arg; }
}

现在,既然你不能在同一个脚本中有条件地检查和执行ES6,你必须编写两个不同的脚本:一个只使用ES5,另一个包括ES6功能。使用两个不同的脚本,您将能够导入ES6,只有当它被支持,并且不会导致SyntaxErrors被抛出。

ES6检测和条件执行示例

现在让我们做一个更可靠的例子,让我们说你想在你的ES6脚本中使用这些功能:

>新的符号对象
>使用class关键字构建的类
> Arrow((…)=> {…})函数

注意:新引入的语法(如箭头函数)的特征检测只能使用eval()函数或其他等效函数(例如Function())完成,因为编写无效语法会在执行前停止脚本。这也是为什么你不能使用if语句来检测类和箭头函数的原因:这些特性是关于关键字和语法的,所以一个eval(…)包装在一个try {…} catch(e){.. 。}块将工作正常。

所以,来到真正的代码:

> HTML标记:

<html>
    <head>
        <script src="es5script.js"></script>
    </head>
    <body>
        <!-- ... -->
    </body>
</html>

> es5script.js脚本中的代码:

function check() {
    "use strict";

    if (typeof Symbol == "undefined") return false;
    try {
        eval("class Foo {}");
        eval("var bar = (x) => x+1");
    } catch (e) { return false; }

    return true;
}

if (check()) {
    // The engine supports ES6 features you want to use
    var s = document.createElement('script');
    s.src = "es6script.js";
    document.head.appendChild(s);
} else {
    // The engine doesn't support those ES6 features
    // Use the boring ES5 :(
}

> es6script.js中的代码:

// Just for example...
"use strict";

class Car { // yay!
   constructor(speed) {
       this.speed = speed;
   }
}

var foo = Symbol('foo'); // wohoo!
var bar = new Car(320);  // blaze it!
var baz = (name) => { alert('Hello ' + name + '!'); }; // so cool!

浏览器/引擎检测

就像我上面说的,浏览器和引擎检测不是编程一些JavaScript脚本的最佳做法。我会给你一些关于这个话题的背景,只是不要把我的话作为一个“随机个人意见”。

引用MDN文档[link]:

When considering using the user agent string to detect which browser is being used, your first step is to try to avoid it if possible. Start by trying to identify why you want to do it.

[…] Are you trying to check for the existence of a specific feature?
Your site needs to use a specific Web feature that some browsers don’t yet support, and you want to send those users to an older Web site with fewer features but that you know will work. This is the worst reason to use user agent detection, because odds are eventually all the other browsers will catch up. You should do your best to avoid using user agent sniffing in this scenario, and do feature detection instead.

另外,你说的是使用navigator.appVersion,但是考虑使用另一种方法,因为那个方法和许多其他导航器属性一起被弃用,并且不总是像你想象的那样。

因此,再次引用MDN文档:

Deprecated: this feature has been removed from the Web standards. Though some browsers may still support it, it is in the process of being dropped. Do not use it in old or new projects. Pages or Web apps using it may break at any time.

Note: Do not rely on this property to return the correct browser version. In Gecko-based browsers (like Firefox) and WebKit-based browsers (like Chrome and Safari) the returned value starts with “5.0” followed by platform information. In Opera 10 and newer the returned version does not match the actual browser version, either.

http://stackoverflow.com/questions/29046635/javascript-es6-cross-browser-detection

本站文章除注明转载外,均为本站原创或编译
转载请明显位置注明出处:Javascript ES6跨浏览器检测