Wie kann ich die Javascript-Engine-Version des Browsers und die Unterstützung für ECMAScript 6 herausfinden?
Ich verwende navigator.appVersion
nur, um die Version des Browsers zu kennen, aber nicht die Version der Engine.
javascript
ecmascript-6
Schlag Yang
quelle
quelle
Antworten:
Funktionserkennung
Ich empfehle Ihnen, die Feature-Erkennung zu verwenden, anstatt die Engine des Browsers mit heuristischen Methoden zu erkennen. Dazu können Sie einfach Code in eine
try {..} catch (e) {...}
Anweisung einschließen oder einigeif (...)
Anweisungen verwenden .Zum Beispiel:
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 :( }
Warum ist die Funktionserkennung besser als die Browser- / Engine-Erkennung?
Es gibt mehrere Gründe, die in den meisten Fällen die Feature-Erkennung zur besten Option machen:
Sie müssen sich nicht auf die Version, die Engine oder die Besonderheiten des Browsers verlassen oder diese mit heuristischen Methoden erkennen, die schwer und recht geschickt zu implementieren sind.
Bei der Erkennung von Browser- / Engine-Spezifikationen treten keine Fehler auf.
Sie müssen sich nicht um browserspezifische Funktionen kümmern: Beispielsweise haben WebKit- Browser andere Spezifikationen als andere.
Sie können sicher sein, dass Sie eine Funktion verwenden können, sobald sie erkannt wurde.
Dies sind die Hauptgründe, warum IMHO die Feature-Erkennung zum besten Ansatz macht.
Funktionserkennung + Fallback
Wenn Sie die Feature-Erkennung verwenden , besteht eine ziemlich clevere Arbeitsweise, wenn Sie nicht sicher sind, welche Features Sie verwenden können / nicht, in mehreren Feature-Erkennungen und den daraus resultierenden Rückgriffen auf grundlegendere Methoden (oder sogar die Erstellung dieser Methoden von Grund auf neu), falls die Features vorhanden sind Sie möchten verwenden, werden nicht unterstützt.
Ein einfaches Beispiel für die Feature-Erkennung mit Fallback kann auf das
window.requestAnimationFrame
Feature angewendet werden , das nicht von allen Browsern unterstützt wird und je nach dem Browser, an dem Sie arbeiten, verschiedene Präfixe hat. In diesem Fall können Sie Folgendes leicht erkennen und zurückgreifen :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);
Erkennung von ECMAScript 6 (Harmony) -Funktionen
Kommen wir nun zum eigentlichen Problem : Wenn Sie die Unterstützung für ES6 erkennen möchten, können Sie sich nicht wie oben beschrieben verhalten, da ein relevanter Bereich von ES6-Funktionen auf neuen Syntaxen und privaten Wörtern basiert und ausgelöst wird a
SyntaxError
Wenn in ES5 verwendet , bedeutet dies, dass das Schreiben eines Skripts, das sowohl ES5 als auch ES6 enthält, unmöglich ist!Hier ist ein Beispiel, um dieses Problem zu demonstrieren. Das folgende Snippet funktioniert nicht und wird vor der Ausführung blockiert, da es eine unzulässige Syntax enthält.
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; } }
Da Sie ES6 nicht im selben Skript prüfen und bedingt ausführen können, müssen Sie zwei verschiedene Skripte schreiben : eines, das nur ES5 verwendet, und eines, das ES6-Funktionen enthält. Mit zwei verschiedenen Skripten können Sie das ES6-Skript nur dann importieren, wenn es unterstützt wird und ohne dass
SyntaxErrors
es ausgelöst wird.Beispiel für ES6-Erkennung und bedingte Ausführung
Lassen Sie uns nun ein aussagekräftigeres Beispiel erstellen und diese Funktionen in Ihrem ES6-Skript verwenden:
Symbol
Objekteclass
Schlüsselwort erstellte Klassen(...)=>{...}
) -FunktionenHINWEIS: Die Funktionserkennung neu eingeführter Syntaxen (wie Pfeilfunktionen) kann nur mit der
eval()
Funktion oder anderen Entsprechungen (z. B.Function()
) durchgeführt werden, da das Schreiben einer ungültigen Syntax das Skript vor seiner Ausführung stoppt. Dies ist auch der Grund, warum Sie keineif
Anweisungen zum Erkennen von Klassen und Pfeilfunktionen verwenden können: Diese Funktionen beziehen sich auf Schlüsselwörter und Syntax, sodass eineval(...)
in einentry {...} catch (e) {...}
Block eingeschlossenes Element einwandfrei funktioniert.Kommen wir also zum eigentlichen Code:
HTML-Markup:
<html> <head> <script src="es5script.js"></script> </head> <body> <!-- ... --> </body> </html>
Code in Ihrem
es5script.js
Skript: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 :( }
Code in Ihrem
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!
Browser- / Engine-Erkennung
Wie oben erwähnt, sind die Browser- und Engine-Erkennung nicht die besten Methoden beim Programmieren eines JavaScript-Skripts. Ich werde Ihnen einige Hintergrundinformationen zu diesem Thema geben, nur um meine Worte nicht als "zufällige persönliche Meinung" zu hinterlassen.
Zitat aus der MDN-Dokumentation [ Link ]:
Sie sagen auch, dass Sie verwenden
navigator.appVersion
, erwägen jedoch einen anderen Ansatz, da dieser zusammen mit vielen anderen Navigatoreigenschaften veraltet ist und sich nicht immer so verhält, wie Sie denken.Also noch einmal aus der MDN-Dokumentation [ Link ] zitieren :
quelle
Symbol
. Ich glaube nicht, dass eine Engine alle von ES6 vorgeschlagenen Funktionen unterstützt. Sie müssen nach allen ES6-Funktionen suchen, die Sie verwenden möchten."".startsWith
, aber das war schon immer einfach. Um syntaxbasierte Funktionen zu erkennen, müssen Sie eval () verwenden, um den ungültigen Code vor dem ES5-Parser auszublenden.engineVersion: es5
oder umengineVersion: es6
zu zeigen, dass er dies unterstützt. Wenn dies auch funktionieren sollte, wennflags
es aufon/off
diese Weise gedreht wird, müssen Sie sich nicht auf ein js-script
Tag verlassen, um Ihre Assets zu laden. Der Server sollte in der Lage sein, die richtige Datei oder das richtige Legacy bereitzustellen. aber das ist immer noch eine Meinung :)Browser-Anbieter, die ES6-Module unterstützen, bieten jetzt eine einfache Möglichkeit zur Funktionserkennung:
... <head> <script nomodule>window.nomodules = true;</script> <script>console.log(window.nomodules)</script> </head> ...
Das Skript mit dem
nomodule
Attribut wird von unterstützenden Browsern nicht ausgeführt<script type="module" ...>
Sie können das Skript auch folgendermaßen einfügen:
const script = document.createElement('script'); script.setAttribute('nomodule', ''); script.innerHTML = 'window.nomodules = true;'; document.head.insertBefore(script, document.head.firstChild); script.remove();
quelle
Wie Marco Bonelli sagte, ist die Verwendung von eval () der beste Weg, um die Sprachsyntax von ECMAScript 6 zu erkennen . . Wenn der Aufruf keinen Fehler auslöst, werden "alle anderen" Funktionen unterstützt, aber ich empfehle Function (); .
function isES6() { try { Function("() => {};"); return true; } catch(exception) { return false; } }
Demo: https://jsfiddle.net/uma4Loq7/
quelle
eval()
oderFunction()
ist nicht kompatibel mit einer Inhaltssicherheitsrichtlinie, die nicht angegeben ist'unsafe-eval'
.(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); } })()
quelle
if (window.devicePixelRatio) //If WebKit browser
<= Das ist schlecht. Lesen Sie die Antwort von Marco Bonelli, warum Sie nicht die Browsererkennung verwenden sollten, sondern die Funktionserkennung.Derzeit gibt es keine genaue Methode zum Erkennen von ES6. Wenn Sie jedoch die Funktionen im aktuellen Browser testen, können Sie feststellen, ob es sich bei der Engine um ES6 handelt. Meine esx- Bibliothek erkennt die ECMAScript-Version durch Syntaxtests und Methodenprüfungen. Wissen Sie, dass es ECMAScript 3, 5, 6 und 7 erkennen kann (ES7 nicht getestet, sollte aber funktionieren), wenn kein ECMAScript-Test übereinstimmt, gibt es
null
als Ergebnis.Beispiel mit meiner Bibliothek:
if (esx.detectVersion() >= 6) { /* We're in ES6 or above */ }
quelle
eval()
Zeile 46 inesdetect.js
diesem Repository ist nicht mit einer Inhaltssicherheitsrichtlinie kompatibel, die nicht angegeben ist'unsafe-eval'
.Wie Damian Yerrick erwähnt hat, ist die Verwendung von eval () oder Function () nicht mit einer Richtlinie zur Inhaltssicherheit kompatibel, in der nicht "unsicher-eval" angegeben ist.
Wenn der Browser Worker unterstützt, können Sie die Unterstützung für jede ES6-Syntax erkennen, indem Sie diese Syntax in einem Worker implementieren und auf Fehler oder Erfolge prüfen, z. B. um die Unterstützung für Pfeilfunktionen zu erkennen:
worker.js
// If ES6 arrow functions are supported then the worker listener will receive true, otherwise it will receive an error message (() => { postMessage(true); })();
index.js
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) } }
quelle
Wenn Sie eval aus irgendeinem Grund nicht verwenden können, können Sie dies global erkennen, indem Sie den Skriptcode in einen eigenen Skriptblock einfügen (und entweder den Wert einer Variablenzuweisung im Block testen oder window.onerror verwenden).
<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>
https://jsfiddle.net/s5tqow91/2/
Bitte beachten Sie, dass es viele ES6-Funktionen gibt und die Überprüfung nur einer nicht garantiert, dass Sie abgedeckt sind. (Der obige Code deckt auch nicht alles ab, ich denke, es sind genau die Funktionen, die ich am häufigsten benutze).
Außerdem gibt es eine ziemlich beliebte npm-Bibliothek, die all diese Dinge zu behandeln scheint: https://www.npmjs.com/package/feature-detect-es6
quelle
Fügen Sie den inkompatiblen Syntaxcode, z. B. mit Pfeilfunktionen, in einen eigenen Skriptblock ein und füllen Sie ihn mit kompatiblem Syntaxcode.
<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>
quelle