[解決済み] 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 のサポートを検出したい場合、私が上で言ったような動作はできません。
を投げてしまうからです。
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 it contains illegal syntax.
} else {
var bar = function(arg) { return arg; }
}
さて、ES6のチェックと条件付き実行の両方を同じスクリプトで行うことはできないので
の2つのスクリプトを書く必要があります。
を書く必要があります。2つのスクリプトを使えば
ES6がサポートされている場合のみ、ES6の方をインポートする。
を引き起こすことなく、また
SyntaxErrors
をスローさせることなく。
ES6検出と条件実行の例
では、もっと関連性の高い例を作ってみましょう。ES6スクリプトでこれらの機能を使いたいとします。
-
新しい
Symbol
オブジェクト -
で構築されたクラスは
class
キーワード -
矢印(
(...)=>{...}
) の機能
注意
特徴検出
新しく導入された構文の
(矢印関数など)
を使用することでのみ可能です。
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ドキュメントから引用 [... リンク ]:
どのブラウザが使用されているかを検出するためにユーザーエージェント文字列を使用することを検討する場合、最初のステップは、可能であればそれを回避しようとすることです。なぜそうしたいのかを特定することから始めてください。
[...] 特定の機能の存在を確認しようとしているのでしょうか? あなたのサイトでは、一部のブラウザがまだサポートしていない特定の Web 機能を使用する必要があり、それらのユーザーを、機能は少ないが動作することが分かっている古い Web サイトに送りたい場合です。これは、ユーザーエージェント検出を使う理由として最も不適当なものです。このようなシナリオでは、ユーザエージェント検出を使用しないように最善を尽くさなければなりません。 機能検出を行います。 .
また、あなたが使っているのは
navigator.appVersion
を使用していると言っていますが、別のアプローチを使用することを検討してください。なぜなら、その1つは、他の多くのナビゲータ・プロパティと一緒で
非推奨
であり、常にあなたが考えているように動作するわけではありません。
ということで、MDNドキュメントから引用すると、[... リンク ]をもう一度。
非推奨 : この機能はウェブ標準から削除されました。いくつかのブラウザはまだサポートしているかもしれませんが、廃止される方向にあります。古いプロジェクトでも新しいプロジェクトでも、この機能を使わないでください。これを使用したページまたは Web アプリは、いつでも壊れる可能性があります。
注意してください。 正しいブラウザのバージョンを返すために、このプロパティに依存しないでください。Gecko ベースのブラウザ (Firefox など) および WebKit ベースのブラウザ (Chrome や Safari など) では、返される値は "5.0" で始まり、プラットフォーム情報が続きます。Opera 10 およびそれ以降のバージョンでは、返されるバージョンは実際のブラウザのバージョンとも一致しません。
関連
-
[解決済み] 配列から特定の項目を削除するにはどうすればよいですか?
-
[解決済み] JavaScriptで "use strict "は何をするのか、その根拠は?
-
[解決済み] let "と "var "の使い分けは?
-
[解決済み] GUID / UUIDの作成方法
-
[解決済み] JavaScript で配列に値が含まれているかどうかを確認するにはどうすればよいですか?
-
[解決済み] (a== 1 && a ==2 && a==3) が真に評価されることはあるのでしょうか?
-
[解決済み] Reactコンポーネントでthis.setStateを複数回使用するとどうなりますか?
-
[解決済み] react-routerのハッシュフラグメントからクエリパラメータを取得する
-
[解決済み] Chromeの拡張機能開発にWebStormを使用するにはどうすればよいですか?
-
[解決済み] JavaScriptとLuaの微妙な違い [終了しました]
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] JSのDateからDay名
-
[解決済み] ジェスト あるクラスの特定のメソッドをモックする方法
-
[解決済み] 上級者向けJavaScript。この関数はなぜ括弧でくくられるのですか?重複
-
[解決済み] チェックボックスが選択されているかどうかを確認するjQuery
-
[解決済み] なぜJavaScriptでは!{}[true]がtrueに評価されるのですか?
-
[解決済み] JavaScriptで、ある文字列が別の文字列の中に出現するすべてのインデックスを見つけるにはどうすればよいですか?
-
[解決済み] jQueryの$という記号の意味は何ですか?
-
[解決済み] moment.jsでミュータビリティを回避するには?
-
[解決済み] TypeScriptプロジェクトで既存のC#クラス定義を再利用する方法
-
[解決済み] JavaScriptで長い配列を小さい配列に分割する方法