10

次のようなドキュメントの ajax フィードを受信して​​います (かなり単純化されています)。

aDocs = [{title:'new doc', ext:'pdf'}, {title:'another', ext:'xlsx'}];

aDocs 配列を繰り返し処理し、各ドキュメントに関する情報を表示すると同時に、表示用に HTML を変更し、データベースを更新するための API 呼び出しを実行できるメソッドを各ドキュメントに追加します。

ここ__proto__で、既存のオブジェクトにメソッドを追加するには、属性を使用できることを読みました。次のようなもの:

function Doc(){}
Doc.prototype.getExt = function(){return this.ext}
Doc.prototype.getTitle = function(){return this.title}
for (var i=0; i<aDocs.length; i++){
  aDocs[i].__proto__ = Doc.prototype
}

上記の記事によると、これは公式の JavaScript ではなく、IE ではサポートされておらず (サポートされることはありません)、Webkit ブラウザーでは非推奨になる可能性があります。

これは別の刺し傷です:

function getExt(){ return this.ext }
function getTitle(){return this.title}
for (var i=0; i<aDocs.length; i++){
  aDocs[i].getExt = getExt;
  aDocs[i].getTitle = getTitle;
}

この 2 番目の代替案は実行可能で効率的ですか? または、これらの関数を再作成して、冗長なオーバーヘッドを作成していますか?

繰り返しますが、上記の例は単純化されています (aDocs[i].ext上記の問題を解決できることはわかっていますが、表示と API 呼び出しの方法はより複雑です)。

4

3 に答える 3

8

この 2 番目の代替案は実行可能で効率的ですか?

はい。

または、これらの関数を再作成して、冗長なオーバーヘッドを作成していますか?

いいえ、関数は再作成されたものではなく、再利用されました。すべてのオブジェクトは、および関数の1 つのコピーを共有します。(say) からの関数の呼び出し中、呼び出し内で、関数がアタッチされているオブジェクトを参照します。(これは、オブジェクトから取得する式の一部として呼び出す場合にのみ適用されます。たとえば、)getExtgetTitleaDocs[1]thisvar title = aDocs[1].getTitle();

別の方法として、必要に応じて、プロトタイプを共有する新しいオブジェクトを作成し、オブジェクトから新しいオブジェクトにプロパティをコピーすることもできますが、既存のaDocsオブジェクトに新しい関数を割り当てることについて尋ねられたので...

于 2013-03-12T16:55:20.103 に答える
2

多くの場合、プロトタイプを拡張 (メソッドを追加) するのが最善の方法ですが、オブジェクト リテラル (またはJSON.parse の結果) を扱っているため、Object.prototypewhich is not doneを拡張するか、ラッパーを作成する必要があります。必要なメソッドをそのプロトタイプにアタッチしたコンストラクター。問題は次のとおりthisです。その場合に理解する...私はそのままにしておきます.2番目のアプローチを使用してください.単純なループで十分です. その上:プロトタイプメソッドはとにかく(わずかに)遅いです...

関数オブジェクト自体はできるだけ早く作成されます (グローバル名前空間で定義されている場合は、スクリプトが解析されるとすぐに作成されます)。これらのオブジェクトを単純にループし、任意の関数への参照を各オブジェクトに割り当てるだけで、追加の関数を作成することはまったくありません。
これを試してください:

var someObj = {name:'someObj'}, 
anotherObj = {name: 'anotherObj'},
someFunction = function()
{
    console.log(this);
};
someObj.func = someFunction;
anotherObj.func = someFunction;
//or, shorter
someObj.func = anotherObj.func = someFunction;
//therefore:
console.log(someObj.func === anotherObj.func);//logs true! there is only 1 function object
someObj.func();//logs {name: 'someObj'}
anotherObj.func();//logs: {name: 'anotherObj'}

この問題をより深く扱った多くの質問 (および回答) が投稿されているので、興味がある場合は:

javascript のオブジェクトと関数
John Resig の JavaScript クラス継承実装を使用すると、'Class' の代わりにサブクラス名
が出力される
JavaScript の「クラス」定義のこれら 3 つのパターンの違いは何ですか?

すべてがあなたの質問に多かれ少なかれ関連しています

于 2013-03-12T17:03:27.910 に答える
1

この場合、オブジェクトを Doc のコンストラクターに渡すだけです。

function Doc(obj){
   this.obj = obj;
}

Doc.prototype.getExt = function(){
    return this.obj.ext;
}
Doc.prototype.getTitle = function(){
   return this.obj.title;
}

var docs = [];
for (var i=0; i<aDocs.length; i++){
  docs.push(new Doc(aDocs[i]));
}

あなたのアプローチには2つの問題があります:

  • インスタンスごとに各メソッドを個別にコピーする必要があります。
  • あなたの「クラス」はどこにも文書化されていません。クラスにすることで、オブジェクトがそれらのメソッドを持っていることがより明確になります。
于 2013-03-12T16:58:49.850 に答える