0

誰かがArray.prototype.filter古いブラウザ用の関数 (例: ) を実装したい場合、どの方法が優れていますか? なんで?それぞれの長所と短所は何ですか?

if (!Array.prototype.filter) {
  Array.prototype.filter = function() {
    //implementation
  }
}

また

function myFilter(e,i,f) {
    if (!Array.prototype.filter) {
        //implementation
    } else {
        return Array.prototype.filter(e,i,f);
    }
}
4

3 に答える 3

2

個人的には、ほとんどの場合、最初のアプローチ(追加Array.prototype.filter)を使用しますが、使用しない場合もあります。古いブラウザ用の大規模なフレームワークを作成するときは、最初のアプローチを使用しません。古いブラウザは、悪いスクリプトを含め、インターネット上の他のスクリプトとうまく連携する必要があります。

考慮すべき点は次のとおりです。あなたが説明した方法を使用するのをやめ、Array.prototype.filter次に次のようなことをするサードパーティのスクリプトをWebサイトに追加するとします。

var someArray = [ 'a', 'b', 'c' ];
console.log('The first three letters of the alphabet are: ');
for (var i in someArray)
    console.log(someArray[i]);

結果?

The first three letters of the alphabet are: 
a
b
c
function () { ... }

フィルタ機能が出力されます!現在、技術レベルでは、for...inループを使用して配列を反復することはできませんが、サードパーティのスクリプトが実行する可能性のある処理を制御することはできません。これが主な欠点であり、インターネット全体で使用される大規模なライブラリを作成する場合は、検討する価値があります。

これにより、期間に何かを追加できなくなりますObject.prototype(単純なObject.prototype.method = function(){...} assignment), becausefor ... in is good to use on other types of objects, and this kind of shimming breaksfor...in`を使用します。

ただし、自分のWebサイトで使用するコードを記述しているだけで、含めるスクリプトが高品質であり、このような過ちを犯さないことがわかっている場合は、これは優れた手法です。

さらに、コードがECMAScript 5準拠のブラウザーのみを対象としている場合は、シムを列挙不可として定義できます。これにより、シムがfor...inループに表示されなくなります。私は現在、ECMAScript 6メソッドをES5ブラウザーにシムするプロジェクトに取り組んでいます。これは、ES5ブラウザーでのみ実行することを目的としているため、次のことを回避できます。

Object.defineProperty(Array.prototype, 'contains', {
    value: function(value) {
        // Implementation
    },
    enumerable: false,
    writable: true,
    configurable: true
});

このようにシムを定義すると、シムがループに表示されないようにするため、実装が仕様/ドラフトに正確に従っている限り、for...in使用しても安全です。Object.prototype

これは二次的なポイントをもたらします。仕様に従ってメソッドを正確に実装できるかどうか確信が持てない場合は、シムインしない方がよい場合もあります。これにより、組み込みをチェックして使用可能な場合はそれを使用するライブラリが破損する可能性がありますが、何かにフォールバックします。そうでない場合。実装が壊れている場合よりも、何もせずにそのままにしておく方がよいでしょう。

このため、シムを部分的に実装しようとはしません。たとえばObject.create、ES3ブラウザで完全に実装することはできないので、これをシムすることはありません。私は自分のmyLibrary.create関数を使用していますが、これは同じように機能する可能性がありますが、少なくとも、存在をチェックする可能性のあるコードObject.createは、完全に機能するバージョンであると誤解されていません。

話の教訓:シムを使用する場合は、MDNで仕様に準拠した非常に優れたシムをいくつかチェックして、次のようなコードの記述方法を学習してください:Array.prototype.filter


最後の注意:多くのライブラリがメソッドを使用しない理由Array.prototypeは、これらの考慮事項の一部にある可能性がありますが、これらのケースの多くには歴史的な理由もあります。以前 に開発されていたjQueryのようなライブラリfilterは、標準の組み込みメソッドでした。Prototype.jsは、非標準のメソッドを追加するアプローチを採用しました。これには、上記で説明したメソッドよりも多くの欠点があります。jQueryは、組み込みのプロトタイプに非標準のメソッドを追加しないことを決定しました。そのため、これらのメソッドにはが含まれています$.filter

于 2012-11-12T04:02:57.613 に答える
1

2番目のアプローチがより一般的です。これは、jQueryやUnderscore.jsなどの人気のあるshimJSライブラリで使用されています。

とはいえ、ネイティブオブジェクトの拡張は、ホストオブジェクトの拡張よりもはるかに危険性が低くなります(後者の場合、通常は「キャッチ22」です。ホストオブジェクトの拡張を十分に処理しないブラウザで追加機能を提供するために、ネイティブオブジェクトを拡張します)。この記事はそれを要約します:

適切で準拠したシムを書くのは難しいことを忘れないでください。疑わしい場合は、スタンドアロンオブジェクトを使用してください。シミングしているメソッドが未完成の仕様の一部である場合は、スタンドアロンオブジェクトを使用します。メソッドのコンプライアンスについて確信があり、メソッドが完成した将来性のある仕様の一部である場合にのみ、ネイティブオブジェクトを直接シムすることが安全です。

于 2012-11-07T17:14:05.990 に答える
0

新しい標準の js 関数とクラスのベスト プラクティスはshimingで、関数が古いブラウザーで見つからない場合はクラスを拡張します。

ただし、関数が標準にならない場合は、新しい関数を作成し、標準クラスを変更しないことをお勧めします。これは、将来別の動作で使用される可能性のある関数名を使用すると、アプリが破損するためです。

于 2013-01-31T05:06:49.370 に答える