私は実際にこの種のベンチマークを行いました.メモリが機能する場合、プロトタイプモデルは通常、値をオブジェクトに直接割り当てるよりも遅くなります. 例外は、インスタンスの大部分が同一であり、インスタンス化がプロパティ アクセスよりもはるかに頻繁に発生する場合です。
したがって、次のようにオブジェクトを定義すると:
var Class = function() {};
Class.prototype.p1 = 1;
Class.prototype.p2 = 1;
Class.prototype.p3 = 1;
プロパティを各オブジェクトにコピーすることで、インスタンス化時のパフォーマンス ヒットを回避できます。しかし、そのパフォーマンスは、それらのプロパティがアクセスまたは変更されると頭角を現します。また、これらのプロパティを変更せずにアクセスすると、アクセスするたびにプロトタイプ チェーンをたどるというパフォーマンス ヒットが発生します (ローカル インスタンスにコピーされないため)。しかし、多くのプロパティがあり、インスタンスごとに少数のプロパティにしかアクセスできない場合は、おそらくこれが理想的です。
for (var i = 0; i < 100000; i++) {
var x = new Class();
console.log(x.p1);
// ignore p2-p99. we don't need them right now.
}
スペクトルの反対側では、少数のインスタンスでプロパティを何度も反復する必要がある場合は、プロトタイプ チェーンをたどるヒットを回避した方がよいでしょう。
var Class = function() {
this.p1 = 1;
this.p2 = 1;
this.p3 = 1;
}
各インスタンスは、作成時に p1、p2、および p3 の独自のコピーを取得します。また、プロトタイプ チェーンは、それらのいずれかにアクセスするときに参照する必要はありません。
var instances = [
new Class(), new Class(), new Class()
];
for (var i = 0; i < 1000000; i++) {
console.log(instances[i % instances.length].p1);
console.log(instances[i % instances.length].p2);
console.log(instances[i % instances.length].p3);
}
後で時間があれば、後でこれをベンチマークして検証します。それまでは、私があなたに提供できるのは理論だけです!
補遺
プロトタイプを使用すると、必ずしもパフォーマンスに関連するわけではありませんが、2 つのメリットがあります。
1 つは、比較的静的なプロパティ (関数など) の場合、メモリを節約します。ほとんどのアプリケーションは、制限にぶつかることはありません。ただし、オフチェンジではこれが問題になるため、プロトタイプを使用してください。
2 つ目は、プロトタイプを使用すると、クラスの既存のすべてのインスタンスに関数とプロパティを割り当てることができることです。インスタンス レベルのプロパティで同じ偉業を達成するには、検索して反復する必要があります。
ベンチマーク
最新バージョンの FF と Chrome for OS X でのみ実行した最新のベンチマークに従って、単一層 (継承されていない) クラス定義に次の構文を使用しました。
プロトタイプ。*
function Class() {}
Class.prototype.a = 1;
Class.prototype.b = 2;
Class.prototype.c = 3;
これ。*
function Class() {
this.a = 1;
this.b = 2;
this.c = 3;
}
上記の 2 つの構文の間で、this.*
構文は全体的に約 10.5% 高速に動作します。
継承のレベルを追加して、次を使用しました。
プロトタイプ。*
function Base() {}
Base.prototype.a = 1;
Base.prototype.b = 2;
Base.prototype.c = 3;
function Class() {}
Class.prototype = new Base();
これ。*
function Base() {
this.a = 1;
this.b = 2;
this.c = 3;
}
function Class() {
Base.apply(this);
}
この場合、このprototype.*
構文は全体で約 38.5% 高速であることがわかりました。this.*
構文は、メンバ アクセスのブラウザ間で合計すると、まだわずかに高速でした。しかし、この利点は、インスタンス化の利点ほど顕著ではありませんでした。
また、継承へのハイブリッド アプローチのベンチマークも行いました。
function Base() {
this.a = 1;
this.b = 2;
this.c = 3;
}
function Class() {
}
Class.prototype = new Base();
全体として、構文よりも約 0.5% 高速に実行されましたprototype.*
(おそらく重要ではありません)。ただし、興味深いことに、インスタンス化中はprototype.*
構文よりも約 1% 遅くなりましたが、メンバー アクセス中は約 2% 高速でした。繰り返しますが、それほど重要ではありませんが、継承の深さが増すにつれて、これらの利点が拡大するかどうか疑問に思わずにはいられません。
もちろん、これらのベンチマークは十分に管理された環境で行われたものではないことに注意してください。私は、パフォーマンスの著しく広いギャップが重要であると見なす傾向があります. ただし、パーセンテージが低いのは、マシンの CPU 負荷が変動していることが原因である可能性が非常に高くなります。
とはthis.*
いえ、継承が行われていない場合や、クラスのインスタンス化よりもメンバー アクセスがはるかに一般的な場合には、 を使用することをお勧めします。もちろん、Web アプリのパフォーマンスを最大限に引き出す必要がない場合は、自分とチームにとってより直感的な構文を使用してください。ほとんどの Web アプリでは、オブジェクト構築スタイルの違いよりもはるかに大きなパフォーマンス ヒットが発生します。
たとえば、背景色の変更、
document.body.style.backgroundColor = 'blue';
...ベンチマークした最悪のコンストラクターをインスタンス化するよりも約70% 遅くなります。