Подтвердить что ты не робот

Обнаружение кросс-браузера Javascript ES6

Как я могу узнать версию браузера Javascript и поддержку ECMAScript 6?

Я использую navigator.appVersion только для того, чтобы узнать версию браузера, но не версию двигателя.

4b9b3361

Ответ 1

Обнаружение функции

Я предлагаю вам использовать обнаружение функции вместо обнаружения механизма браузера с помощью эвристических методов. Для этого вы можете просто обернуть некоторый код внутри оператора 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 (Гармония)

Теперь, придя к реальной проблеме: если вы хотите обнаружить поддержку ES6, вы не сможете вести себя так, как я сказал выше, потому что соответствующий диапазон ES6 функции основаны на новых синтаксисах и частных словах и будут бросать SyntaxError, если они используются в ES5, что означает, что запись script, которая содержит как 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 условно в том же script, , вам придется написать два разных сценария: один, который использует только ES5, а другой - ES6. С помощью двух разных сценариев вы сможете импортировать ES6 один, только если он поддерживается, и не вызывать SyntaxErrors.

Пример обнаружения ES2 и условного выполнения

Теперь давайте сделаем более подходящий пример и предположим, что вы хотите использовать эти функции в своем ES6 script:

  • Новые объекты Symbol
  • Классы, построенные с ключевым словом class
  • Функции стрелок ((...)=>{...})

ПРИМЕЧАНИЕ: функция обнаружения новых введенных синтаксисов (например, функции стрелок) может выполняться только с помощью функции eval() или других эквивалентов (например, Function()), потому что при написании недопустимого синтаксиса перед тем, как его выполнение, остановится script. Это также причина, по которой вы не можете использовать операторы if для определения классов и функций стрелок: эти функции относятся к ключевым словам и синтаксису, поэтому eval(...), завернутый внутри блока try {...} catch (e) {...}, будет работать нормально.

Итак, переход к реальному коду:

  • Разметка HTML:

    <html>
        <head>
            <script src="es5script.js"></script>
        </head>
        <body>
            <!-- ... -->
        </body>
    </html>
    
  • Код в вашем es5script.js script:

    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 script. Я расскажу вам немного информации по этой теме, просто чтобы не оставлять мои слова "случайным личным мнением".

Цитата из документации MDN [ссылка]:

При рассмотрении использования строки пользовательского агента для определения того, какой браузер используется, первым шагом является попытка избежать его, если это возможно. Начните с определения того, почему вы хотите это сделать.

[...] Вы пытаетесь проверить наличие определенной функции?На вашем сайте должна использоваться определенная веб-функция, которую некоторые браузеры еще не поддерживают, и вы хотите отправить этих пользователей на более старый веб-сайт с меньшим количеством функций, но вы знаете, что это будет работать. Это худшая причина для использования обнаружения пользовательского агента, потому что в конечном итоге все остальные браузеры наверстают упущенное. Вы должны сделать все возможное, чтобы избежать использования нюхающего агента пользователя в этом сценарии и выполнить обнаружение функции.

Кроме того, вы говорите, что используете navigator.appVersion, но считаете, что используете другой подход, потому что этот, вместе со многими другими свойствами навигатора, устарел и не всегда ведет себя так, как вы думаете.

Итак, снова ссылаемся на документацию MDN [ссылка]:

Устаревший: эта функция была удалена из веб-стандартов. Хотя некоторые браузеры все еще могут его поддерживать, он находится в процессе отбрасывания. Не используйте его в старых или новых проектах. Страницы или веб-приложения, использующие его, могут прерываться в любое время.

Примечание. Не полагайтесь на это свойство, чтобы вернуть правильную версию браузера. В браузерах на базе Gecko (например, Firefox) и браузерах на основе WebKit (например, в Chrome и Safari) возвращаемое значение начинается с "5.0", за которым следует информация о платформе. В Opera 10 и новее возвращаемая версия не соответствует реальной версии браузера.

Ответ 2

Используйте следующий код для его обнаружения. Он работает в моем браузере, и вы увидите ES6 на Firefox:)

  • Обнаружение devicePixelRatio, которое является особым свойством в WebKit.
  • Обнаружение функции javaEnabled.

(function() {
  var v8string = 'function%20javaEnabled%28%29%20%7B%20%5Bnative%20code%5D%20%7D';
  var es6string = 'function%20javaEnabled%28%29%20%7B%0A%20%20%20%20%5Bnative%20code%5D%0A%7D';

  if (window.devicePixelRatio) //If WebKit browser
  {
    var s = escape(navigator.javaEnabled.toString());
    if (s === v8string) {
      alert('V099787 detected');
    } else if (s === es6string) {
      alert('ES6 detected')
    } else {
      alert('JSC detected');
    }
  } else {
    display("Not a WebKit browser");
  }

  function display(msg) {
    var p = document.createElement('p');
    p.innerHTML = msg;
    document.body.appendChild(p);
  }

})()

Ответ 3

Пока нет точного способа обнаружения ES6, но если вы проверите его функции в текущем браузере, вы можете определить, является ли движок ES6. Моя библиотека esx обнаруживает версию ECMAScript, выполняя проверку синтаксических тестов и методов. Для того, чтобы знать, что он может обнаружить ECMAScript 3, 5, 6 и 7 (ES7 не проверен, но должен работать), если нет теста ECMAScript, он дает результат null.

Пример использования моей библиотеки:

if (esx.detectVersion() >= 6) {
    /* We're in ES6 or above */
}