ホームページ > ウェブフロントエンド > jsチュートリアル > JavaScript機能の検出が失敗したとき

JavaScript機能の検出が失敗したとき

尊渡假赌尊渡假赌尊渡假赌
リリース: 2025-02-22 09:57:12
オリジナル
805 人が閲覧しました

When JavaScript Feature Detection Fails

キーポイント

  • JavaScript機能検出(プログラマーが使用したいテスト機能)は、常に信頼できるとは限りません。たとえば、Ajax要求のインターネットエクスプローラーでActiveXObjectをテスト、HTML属性はDOMプロパティにマッピングされた属性、ユーザーの動作(タッチデバイスの検出など)に関する仮定などです。
  • 機能検出に失敗すると、ブラウザの検出が必要な場合があります。ただし、ナビゲーター情報の代わりに独自のオブジェクトテストを使用し、それを使用してブラウザを含めるのではなく除外することをお勧めします。
  • ブラウザ検出を実装する場合は非常に注意してください。フィーチャテストと完全に一致していると仮定し、特徴が予想どおりに機能しないことがわかっている場合にのみブラウザ検出を求めてください。さらに、オブジェクトと機能テストに使用される構文は、検出の成功率に影響を与える可能性があるため、適切な構文を選択することが重要です。

昔々、ブラウザ検出はJavaScriptプログラマーの最高のスキルでした。一部の機能がIE5で機能しますが、Netscape 4では機能しないことがわかっている場合は、ブラウザをテストし、それに応じてコードを変更します。たとえば、

if (navigator.userAgent.indexOf('MSIE 5') != -1) {
  // 我们认为此浏览器是 IE5
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

しかし、私が最初に業界に参加したとき、武器競争はすでに始まっていました!ベンダーはユーザーエージェント文字列に追加の値を追加しているため、競合他社のブラウザや独自の値のように見えます。たとえば、これはMacのSafari 5です:

<code>Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/534.59.10 (KHTML, like Gecko) Version/5.1.9 Safari/534.59.10</code>
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
これは、「Safari」、「WebKit」、および「KHTML」のテスト(WebKitの基礎となるKonquerorコードベース)と一致します。 Mozilla ""(歴史的な理由から、ほとんどすべてのブラウザがMozillaであると主張しています)。

これらすべての値を追加する目的は、ブラウザ検出を回避することです。スクリプトがFirefoxのみが特定の機能を処理できると想定している場合、Safariは機能しても除外される場合があります。ユーザーがユーザーエージェントを自分で変更できることを忘れないでください。ブラウザを設定して「GoogleBot/1.0」を認識して、サイト所有者がクロールのみを使用すると思うものにアクセスできるようにしました。

したがって、時間が経つにつれて、この種のブラウザの検出は不可能な混乱になり、ほとんどが使用されていないため、より良いものに置き換えられています。

機能検出は、使用する機能をテストするためだけです。たとえば、

(ビューポートに対する要素の位置を取得する)が必要な場合、ブラウザではなく、ブラウザがサポートされるかどうかが重要ですテスト機能自体よりも悪い:getBoundingClientRect この関数をサポートしていないブラウザは、「未定義の」タイプを返すため、条件は渡されません。特定のブラウザでスクリプトをテストすることなく、正しく機能するか、静かに失敗することがわかります。

または私たち…?

しかし、真実は - 機能検出が完全に信頼できるわけではありません - 時には失敗することがあります。それでは、今すぐいくつかの例を見て、各ケースを解決するためにできることを見てみましょう。

ActiveXオブジェクト

おそらく、機能検出障害の最も有名な例は、インターネットエクスプローラーでのAJAX要求のActiveXObjectをテストすることです。

ActiveXは後期のオブジェクトの例であり、実際的に重要なのは、を使用しようとするまで

if (navigator.userAgent.indexOf('MSIE 5') != -1) {
  // 我们认为此浏览器是 IE5
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
をサポートしているかどうかがわからないことです。したがって、ユーザーがActiveXを無効にした場合、次のコードにエラーが発生します。

これを修正するには、例外ハンドリングを使用する必要があります - オブジェクトをインスタンス化する必要がありますcatch fielures>それに応じて処理します。

<code>Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/534.59.10 (KHTML, like Gecko) Version/5.1.9 Safari/534.59.10</code>
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
html属性はdom属性

にマッピングされました

属性マッピングは、HTML5プロパティで使用されるAPIのサポートをテストするためによく使用されます。たとえば、ドラッグ可能なプロパティを探すことにより、

の要素がDraggable APIをサポートするかどうかを確認します。 [draggable="true"]

ここでの問題は、IE8以前がすべての
if (typeof document.documentElement.getBoundingClientRect != "undefined") {
  // 浏览器支持此函数
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
HTMLプロパティをDOMプロパティに自動的にマッピングすることです。これが、これらの古いバージョンでは

が非常に混乱している理由です。なぜなら、プロパティをまったく返すのではなく、DOMプロパティを返すからです。 これは、getAttribute属性を既に持っている要素を使用する場合を意味します:

それから、それらがサポートされていなくても、IE8以前はに対して

を返します。
if (typeof window.ActiveXObject != "undefined") {
  var request = new ActiveXObject("Microsoft.XMLHTTP");
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

属性は何でもできます:true ("draggable" in element)

しかし、結果は同じです-IE8以前は

に対して

を返します。
if (typeof window.ActiveXObject != "undefined") {
  try {
    var request = new ActiveXObject("Microsoft.XMLHTTP");
  } catch (ex) {
    request = null;
  }
  if (request !== null) {
    //... 我们有一个请求对象
  }
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

この場合、解決策は、テストの属性を持たない要素を使用することです。最も安全な方法は、作成された要素を使用することです。 true ユーザーの動作に関する仮定("nonsense" in element)

次のコードを使用してタッチデバイスを検出したことがあるかもしれません:

if ("draggable" in element) {
  // 浏览器支持拖放
}
ログイン後にコピー
ログイン後にコピー
ほとんどのタッチデバイスは、クリックイベント(通常は約300ミリ秒)をトリガーする前に手動の遅延を実装します。これは、クリック中に要素をクリックしないようにするためです。しかし、これによりアプリケーションが遅くて反応しないと感じるため、開発者はこの機能テストを使用してイベントを分岐することがあります。

ただし、この条件は、

- デバイスがタッチをサポートするため、タッチが使用されるため、

誤差に由来します。しかし、タッチスクリーンラップトップはどうですか?ユーザーは画面に触れているか、上記のコードを使用できないため、マウスでクリックすることは何も実行できません。
<div draggable="true"> ... </div>
ログイン後にコピー
この場合、ソリューションはイベントサポートをまったくテストすることではありません - 代わりに2つのイベントを同時にバインドしてから、

を使用して、タッチがクリックを生成するのを防ぎます。

if (navigator.userAgent.indexOf('MSIE 5') != -1) {
  // 我们认为此浏览器是 IE5
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
まったく機能しないもの

これが苦痛であることを認めるが、テストする必要がないことは機能ではないことがあります - ではなく、ブラウザ - 特定のブラウザが機能しないものをサポートすると主張しているためです。最近の例は、Opera 12のsetDragImage()です(オブジェクトをドラッグアンドドロップする方法です)。 dataTransfer

機能テストは、エラーを投げかけないため、オペラ12がそれをサポートすると主張しているためです。うまくいかないだけです:

<code>Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/534.59.10 (KHTML, like Gecko) Version/5.1.9 Safari/534.59.10</code>
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
さあ、

を試してカスタムドラッグイメージを追加し、デフォルト値をサポートなしで喜んで保持したい場合(これは起こります)、これは問題ないかもしれません。ただし、アプリケーションがカスタム画像が必要な場合は、まったく異なる実装を使用する必要があるように(つまり、カスタムJavaScriptを使用してすべてのドラッグ動作を実装)する必要がある場合はどうなりますか?

またはブラウザが特定の機能を実装しているが、避けられないレンダリングエラーがある場合はどうなりますか?問題のあるブラウザを明示的に検出し、使用をサポートしようとした機能から除外する以外に選択肢がない場合があります。

問題は、ブラウザ検出を達成するための最も安全な方法は何ですか?

2つの提案があります

    ナビゲーター情報よりも独自のオブジェクトテストを好む。
  1. これを使用して、ブラウザを含めるのではなく除外します。
  2. たとえば、
オブジェクト検出オペラを12以前に使用できるため、この除外を使用してドラッグ可能なサポートをテストできます。

新しいブラウザがリリースされた場合、テスト結果が変更される可能性は低いため、標準オブジェクトの代わりに独自のオブジェクトを使用する方が良いです。これが私のお気に入りの例のいくつかを紹介します:window.opera

if (typeof document.documentElement.getBoundingClientRect != "undefined") {
  // 浏览器支持此函数
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
オブジェクトテストは、特定のブラウザの特定の機能のサポートを決定するために、または緊急の場合のより正確なブラウザ条件を定義するために、機能テストと組み合わせて使用​​することもできます。

ユーザーエージェントの文字列は信頼できない混乱であることに気付きましたが、ベンダーの文字列は実際には非常に予測可能であり、ChromeまたはSafariを確実にテストするために使用できます。
if (typeof window.ActiveXObject != "undefined") {
  var request = new ActiveXObject("Microsoft.XMLHTTP");
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

これらすべての黄金律は非常に注意することです。可能な限り多くのブラウザで条件をテストし、順方向の互換性を慎重に検討してください。目標は、ブラウザの条件を使用して

ブラウザを除外することです。既知の機能(これは機能テストの目的です)
if (typeof window.ActiveXObject != "undefined") {
  try {
    var request = new ActiveXObject("Microsoft.XMLHTTP");
  } catch (ex) {
    request = null;
  }
  if (request !== null) {
    //... 我们有一个请求对象
  }
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

基本的に、機能テストが完全に一致していると常に仮定します - これが当てはまらないことがわからない限り、機能は予想どおりに機能します。

if ("draggable" in element) {
  // 浏览器支持拖放
}
ログイン後にコピー
ログイン後にコピー
テスト構文を選択

を選択します 終了する前に、オブジェクトとプロパティテストに使用できるさまざまなタイプの構文をチェックしたいと思います。たとえば、近年、次の構文が一般的になりました。

if (navigator.userAgent.indexOf('MSIE 5') != -1) {
  // 我们认为此浏览器是 IE5
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

IE5とその同様の製品が構文のためにエラーを投げるため、過去に使用することはできませんでした。

本質的に、それは次のものとまったく同じですが、書く方が短いです:

<code>Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/534.59.10 (KHTML, like Gecko) Version/5.1.9 Safari/534.59.10</code>
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ただし、テスト条件は通常、自動型変換に依存しています:

if (typeof document.documentElement.getBoundingClientRect != "undefined") {
  // 浏览器支持此函数
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
この構文をいくつかのブラウザオブジェクトテスト(例:

テスト)の早い段階で使用しました。これは、オブジェクトの評価方法のために安全です - 定義されたオブジェクトまたは関数は常に真であると評価され、定義されていない場合、偽として評価されます。 window.opera

しかし、nullまたは空の文字列を効果的に返すものをテストしている可能性がありますが、どちらもfalseに評価されます。たとえば、

属性は、IE6を除外するために時々使用されることがあります:style.maxWidth

if (typeof window.ActiveXObject != "undefined") {
  var request = new ActiveXObject("Microsoft.XMLHTTP");
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

属性maxWidthがサポートされ、に著者が定義された値を持っている場合にのみTrueに評価されます。したがって、このようなテストを書くと、失敗する可能性があります。

一般的なルールは次のとおりです。自動型変換に依存することは、オブジェクトや関数にとって安全ですが、nullの文字列や数字または値に対して必ずしも安全ではありません。
if (typeof window.ActiveXObject != "undefined") {
  try {
    var request = new ActiveXObject("Microsoft.XMLHTTP");
  } catch (ex) {
    request = null;
  }
  if (request !== null) {
    //... 我们有一个请求对象
  }
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
言われていると言われている - 安全に使用できる場合は、通常、最新のブラウザーではるかに高速であるため(おそらくこのタイプの状態に最適化されているため)。

これの詳細については、現実世界での自動タイプ変換を参照してください。

JavaScript機能検出に関するよくある質問

JavaScript機能の検出とは何ですか?なぜそれが重要なのですか?

JavaScript機能検出は、ユーザーのブラウザが特定の機能またはAPIをサポートするかどうかを判断するために開発者が使用するテクノロジーです。これは、すべてのブラウザがJavaScriptのすべての機能をサポートしているわけではないため、重要です。機能検出を使用することにより、開発者はサポートされていない機能に代替ソリューションまたはフォールバックを提供し、さまざまなブラウザーでWebサイトまたはアプリケーションが正しく実行されるようにします。これにより、ユーザーエクスペリエンスが向上し、互換性が保証されます。

JavaScriptの特徴検出はどのように失敗しますか?

javaScript機能検出は、いくつかの理由で失敗する場合があります。よくある理由は、機能検出コードが誤って実装されていることです。たとえば、コードがオブジェクトに存在しないプロパティをチェックすると、未定義に戻り、偽ネガになります。もう1つの理由は、ブラウザの癖やエラーである可能性があります。これにより、機能検出が不正確な結果をもたらす可能性があります。

機能検出とブラウザ検出の違いは何ですか?

機能検出には、ユーザーのブラウザが特定の機能をサポートするかAPIをサポートするかどうかを確認し、ブラウザー検出はユーザーのブラウザとバージョンを認識します。どちらの手法も互換性と機能を確保するように設計されていますが、ブラウザの種類やバージョンに基づいてサポートを想定するのではなく、機能を直接チェックするため、機能の検出はより良い練習と見なされることがよくあります。

JavaScriptを使用してモバイルデバイスを検出する方法は?

JavaScriptのnavigator.userAgent属性を使用して、モバイルデバイスを検出できます。このプロパティは、ブラウザのユーザーエージェントヘッダーを表す文字列を返します。この文字列の特定のキーワード(「Android」、「iPhone」、「iPad」など)をチェックすることにより、ユーザーがモバイルデバイスにいるかどうかを判断できます。

feature.jsとは何ですか?また、機能の検出にどのように役立ちますか?

feature.jsは、機能検出のための軽量で高速でシンプルなJavaScriptユーティリティです。使用者がブラウザが特定の機能をサポートするかどうかをテストできるようにする使いやすいAPIを提供します。これにより、サポートされていない機能のバックアップソリューションまたは代替ソリューションを提供することで、Webサイトまたはアプリケーションの互換性と機能を強化します。

Modernizrとは何ですか?機能の検出にどのように役立ちますか?

Modernizrは、開発者が古いブラウザーとの互換性を維持しながら、開発者がHTML5およびCSS3機能を活用するのに役立つJavaScriptライブラリです。機能検出を使用して、ブラウザが特定の機能をサポートし、HTML要素にクラスを追加するかどうかを確認し、StyleSheetsまたはJavaScriptの特定のブラウザ機能を見つけることができます。

機能検出にデバイスセクター-JSパッケージを使用するにはどうすればよいですか?

Device-Detector-JSパッケージは、デバイス検出のための強力なツールです。ユーザーエージェントの文字列を解析し、スマートフォン、タブレット、デスクトップ、テレビ、その他のデバイスを検出します。また、ブラウザ、エンジン、オペレーティングシステム、およびその他の有用な情報を検出します。このパッケージを使用して、検出されたデバイスに基づいてWebサイトまたはアプリケーションの動作を調整できます。

機能検出を実装するためのベストプラクティスは何ですか?

機能検出を実装するためのいくつかのベストプラクティスには、次のものが含まれます:Modernizrやfeature.jsなどの信頼性の高いテスト済みライブラリ、さまざまなブラウザーやデバイスで機能検出コードを徹底的にテストします。ブラウザのタイプまたはバージョンに基づいています。

機能検出は、ウェブサイトのパフォーマンスを改善するのに役立ちますか?

はい、機能検出はウェブサイトのパフォーマンスを改善するのに役立ちます。サポートされていない機能を検出し、代替ソリューションまたはフォールバックソリューションを提供することにより、不必要なコードがブラウザで実行されるのを防ぐことができます。これにより、読み込み時間が短縮され、Webサイトの全体的なパフォーマンスが向上します。

さまざまなブラウザでサポートされている最新の機能を理解する方法は?

Web開発の急速な発展の結果、さまざまなブラウザーでサポートされている最新の機能を理解するのは難しい場合があります。ただし、Mozilla Developer Network(MDN)などのリソースを使用できます。JavaScriptドキュメントは、さまざまなブラウザーの機能サポートに関する最新情報を提供できます。

以上がJavaScript機能の検出が失敗したときの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート