Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/468.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript ES6跨浏览器检测_Javascript_Ecmascript 6 - Fatal编程技术网

Javascript ES6跨浏览器检测

Javascript ES6跨浏览器检测,javascript,ecmascript-6,Javascript,Ecmascript 6,如何找到浏览器的Javascript引擎版本和对ECMAScript 6的支持 我使用navigator.appVersion只是为了知道浏览器的版本,而不是引擎的版本 检测devicePixelRatio,这是中的一个特殊属性 检测javaEnabled函数的实现 (函数(){ var v8string='函数%20javaEnabled%28%29%20%7B%20%5B本机%20code%5D%20%7D'; var es6string='函数%20javaEnabled%28%29%2

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

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

  • 检测devicePixelRatio,这是中的一个特殊属性
  • 检测javaEnabled函数的实现
  • (函数(){
    var v8string='函数%20javaEnabled%28%29%20%7B%20%5B本机%20code%5D%20%7D';
    var es6string='函数%20javaEnabled%28%29%20%7B%0A%20%20%20%20%5b本机%20code%5D%0A%7D';
    if(window.devicePixelRatio)//if WebKit浏览器
    {
    var s=escape(navigator.javaEnabled.toString());
    如果(s==v8string){
    警报(“检测到V099787”);
    }else if(s==es6string){
    警报(“检测到ES6”)
    }否则{
    警报(“检测到JSC”);
    }
    }否则{
    显示(“非WebKit浏览器”);
    }
    功能显示(msg){
    var p=document.createElement('p');
    p、 innerHTML=msg;
    文件.正文.附件(p);
    }
    })()
    特征检测 我建议您使用功能检测,而不是使用启发式方法检测浏览器引擎。为此,您可以简单地
    语句中包装一些代码,或者使用一些
    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 :(
    }
    
    为什么特征检测优于浏览器/引擎检测? 在大多数情况下,有多种原因使特征检测成为最佳选择:

    • 您不必依赖于浏览器的版本、引擎或细节,也不必使用难以实现且相当狡猾的启发式方法来检测它们

    • 您不会在浏览器/引擎规格检测方面出错

    • 您不必担心特定于浏览器的特性:例如,浏览器的规格与其他浏览器不同

    • 您可以确信,一旦检测到某个功能,您就能够使用它

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

    特征检测+回退 当使用功能检测时,当您不确定哪些功能可以/不能使用时,一个非常聪明的工作方式是多个功能检测,并随后退回到更基本的方法(甚至从头开始创建这些方法),以防您想要使用的功能不受支持

    具有回退功能的功能检测的一个简单示例可以应用于
    窗口.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);
    
    const script = document.createElement('script');
    script.setAttribute('nomodule', '');
    script.innerHTML = 'window.nomodules = true;';
    document.head.insertBefore(script, document.head.firstChild);
    script.remove();
    
    ECMAScript 6(和声)特征检测 现在,来谈谈真正的问题:如果你想检测到对ES6的支持,你就不能像我上面所说的那样,因为ES6的一系列相关功能都是基于新的语法和私有词,如果在ES5中使用,就会抛出一个
    语法错误
    ,这意味着编写同时包含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 it contains illegal syntax.
    } else {
        var bar = function(arg) { return arg; }
    }
    
    现在,由于不能在同一个脚本中有条件地检查和执行ES6,您必须编写两个不同的脚本:一个只使用ES5,另一个包含ES6功能。使用两个不同的脚本,只有在支持ES6的情况下,您才能导入ES6,并且不会导致抛出语法错误

    ES6检测和条件执行示例 现在,让我们制作一个更相关的示例,假设您希望在ES6脚本中使用以下功能:

    • 新的
      符号
      对象
    • 使用
      class
      关键字构建的类
    • Arrow(
      (…)=>{…}
      )函数
    注意:新引入语法的功能检测(如箭头函数)只能使用
    eval()
    函数或其他等效函数(如
    function()
    )完成,因为写入无效语法将在脚本执行之前停止脚本。这也是为什么不能使用
    if
    语句来检测类和箭头函数的原因:这些特性与关键字和语法有关,因此包装在
    try{…}catch(e){…}
    块中的
    eval(…)
    可以正常工作

    那么,来看看真正的代码:

    • HTML标记:

      
      
    • 您的es5script.js脚本中的代码:

      函数检查(){
      “严格使用”;
      if(typeof Symbol==“undefined”)返回false;
      试一试{
      评估(“类别Foo{}”);
      评估(“var bar=(x)=>x+1”);
      }catch(e){return false;}
      返回true;
      }
      if(check()){
      //引擎支持您想要使用的ES6功能
      var s=document.createElement('script');
      s、 src=“es6script.js”;
      文件。标题。附录子项;
      }否则{
      //引擎不支持这些ES6功能
      //使用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文档[]:

    当考虑使用用户代理字符串来检测正在使用的浏览器时,第一步是尽可能避免使用它。首先,请尝试确定为什么要这样做

    […]<script> // This script block should not compile on incompatible browsers, // leaving the function name undefined. // It can then be polyfilled with a function containing compatible syntax code. function fame() { /* incompatible syntax code such as arrow functions */ } </script> <script> if (typeof fame !== "function") { // alert("polyfill: fame"); function fame() { /* compatible syntax code */ } } </script> <script> // main code fame(); </script>
    function isES6()
    {
        try
        {
            Function("() => {};"); return true;
        }
        catch(exception)
        {
            return false;
        }
    }
    
    ...
    <head>
      <script nomodule>window.nomodules = true;</script>
      <script>console.log(window.nomodules)</script>
    </head>
    ...
    
    const script = document.createElement('script');
    script.setAttribute('nomodule', '');
    script.innerHTML = 'window.nomodules = true;';
    document.head.insertBefore(script, document.head.firstChild);
    script.remove();
    
    // If ES6 arrow functions are supported then the worker listener will receive true, otherwise it will receive an error message
    (() => {
        postMessage(true);
    })();
    
    if (typeof (Worker) !== "undefined") {
    
        var myWorker = new Worker('worker.js');
    
        myWorker.onmessage = function (e) {
            // arrow functions must be supported since we received message from the worker arrow function
        }
    
        myWorker.onerror = function (e) {
            // the worker triggered an error so arrow function not supported (could explicitly check message for syntax error)
        }
    }
    
    <script>
        window.isES6 = false;
    </script>
    <script>
        // Arrow functions support
      () => { };
      
      // Class support
      class __ES6FeatureDetectionTest { };
      
      // Object initializer property and method shorthands
      let a = true;
      let b = { 
        a,
        c() { return true; },
        d: [1,2,3],
       };
      
      // Object destructuring
      let { c, d } = b;
      
      // Spread operator
      let e = [...d, 4];
    
      window.isES6 = true;
    </script>
    
    <script>
    document.body.innerHTML += 'isES6: ' + window.isES6;
    </script>