JavaScript コードの最適化
著者: Gregory Baker、GMail ソフトウェア エンジニア、Erik Arvidsson、Google Chrome ソフトウェア エンジニア
必要な経験: JavaScript の実務知識
クライアント側のスクリプトにより、アプリケーションをより動的でアクティブにすることができますただし、ブラウザによるコードの解析によって効率の問題が発生する可能性があり、このパフォーマンスの違いはクライアントによって異なります。ここでは、JavaScript コードを最適化するためのヒントとベスト プラクティスについて説明します。文字列の連結操作は、Internet Explorer 6 および 7 のガベージ コレクションに大きな影響を与えます。この問題は Internet Explorer 8 では解決されていますが、文字列の連結 IE8 および他の非 IE ブラウザー (Chrome など) ではわずかに効率的です。ユーザーの大部分が Internet Explorer 6 または 7 を使用しているため、文字列の構築方法には細心の注意を払う必要があります。
次のサンプル コードがあります:
コードをコピー
percentWhoDislike
'% のエンジニアがこのルールを嫌います。行の長さの制限は '
' スタイルの目的で使用されます。 '
' そこで問題は、どのようにラッピングを行うべきかということです。';
join メソッドを使用する代わりに、join():
コードをコピーします
percentWhoDislike,
' 文字を折り返す必要がある文字列です。このルールはエンジニアの割合が嫌いです。これは ',
' スタイルの目的ですが、パフォーマンスに影響を与えることは望ましくありません。',
' そこで問題は、ラッピングをどのように行うべきかということです。'
].join() ;
同様に、条件文とループで文字列を連結するのは非効率です:
コードをコピーします
}
正しい方法:
; codeヘルパー関数によって生成された文字列を構築します
Pass 一時的な結果を保持する文字列を避けるために、文字列ビルダー (配列またはヘルパー クラスにすることができます) を関数に渡します。 > たとえば、buildMenuItemHtml_ がリテラル文字列と変数から文字列を構築する必要があり、次の代わりに文字列ビルダーが内部で使用されているとします。
コピー コード
コードは次のとおりです: var strBuilder = [];
for (var i = 0; i < menuItems.length; i ) {
コードをコピーします
コードは次のとおりです:
var strBuilder = []
for (var i = 0; i < ; menuItems.length; i ) {
this.buildMenuItem_(menuItems[i], strBuilder ; baz.Bar のインスタンスを構築するとき、foo に対して新しい関数とクロージャが作成されます:
コードをコピー
コードは次のとおりです:
baz.Bar = function() {
//コンストラクター コード
this.foo = function() {
// メソッドコード
}
;
推奨される方法は次のとおりです:
baz.Bar = function() {
// コンストラクター コード
};
baz.Bar.prototype.foo = function() {
// メソッド コード
};
この方法では、baz.Bar インスタンスがいくつ構築されても、foo に対して作成される関数は 1 つだけであり、
インスタンス変数の初期化は行われません。
は、値型 (非参照) の初期化値を持つ変数宣言/初期化コードをプロトタイプ プロトタイプに直接配置します。これにより、関数が不必要に初期化コードを実行するたびにコンストラクターを呼び出すことがなくなります (このアプローチは、 (初期化値がコンストラクターのパラメーターによって決定されるか、構築時に状態が不確実なインスタンス変数)
たとえば、次のように記述する代わりに、
foo.Bar = function() {
this.prop1_ = 4;
this.prop2_ = true; 🎜>this.prop3_ = [];
this.prop4_ = 'まあ'
}
と書きませんか?
コードをコピー
foo.Bar.prototype.prop1_ = 4; foo.Bar.prototype.prop4_ = 'まあ'; 🎜>
クロージャは注意して使用してください
クロージャは JavaScript の強力で便利な機能ですが、次のような欠点もあります。
クロージャはメモリ リークの最も一般的な原因です。
クロージャの作成は、クロージャを使用せずにインライン関数を作成するよりも大幅に遅くなり、次に例を示します。
コードをコピー
コードは次のとおりです。
コード
コードは次のとおりです:
は次のコードよりもさらに遅くなります:
コードは次のとおりです。
ブラウザが属性を解析するとき。次の例では、スコープ チェーンの各レベルを 1 回チェックする必要があります:
コードをコピー
コードは次のとおりです。 🎜>
var a = 'a';
;
f が呼び出されるとき、参照 a は参照 b よりも遅く、両方とも参照 c よりも遅くなります。
IE でのクロージャの使用の詳細については、
IE JScript パフォーマンスに関する推奨事項 パート 3: JavaScript コードの非効率 を参照してください。
の使用を避ける
<span style="COLOR: #336600">with</span>
コード
でを使用しないでください。スコープチェーンが変更され、他のスコープでの変数の検索が高くなるため、パフォーマンスに非常に悪影響を及ぼします。
ブラウザのメモリ リークを回避します<span style="COLOR: #336600">with</span>
メモリ リークは Web アプリケーションにとって非常に一般的な問題であり、ブラウザのメモリ使用量が増加すると、Web アプリケーションとユーザーのシステムの他の部分の速度が低下する可能性があります。 Web アプリケーションで発生するメモリ リークの割合は次のとおりです。 JavaScript エンジンとブラウザ DOM の C オブジェクト実装の間の循環参照 (たとえば、JavaScript エンジンと Internet Explorer の COM インフラストラクチャの間、または JavaScript エンジンと Firefox の XPCOM インフラストラクチャの間)。
メモリ リークを回避するための経験則をいくつか示します。
イベント システムを使用してイベント ハンドラーをアタッチします
最も一般的な循環参照パターン [DOM 要素 --> イベント ハンドラー --> クロージャ スコープ -->] は、
この記事
で説明されています。この問題を回避するには、十分にテストされたイベント システム (Google doctype、Dojo 、または JQuery.
さらに、IE でインライン イベント ハンドラーを使用すると、別の種類のリークが発生します。これは通常の循環参照リークではなく、メモリ内の一時的な匿名スクリプト オブジェクトのリークです。詳細については、 を参照してください。 Internet Explorer のリーク パターンの解決
の「DOM 挿入オーダー リーク モデル」セクション (
にもあります) JavaScript Kit チュートリアル にも例があります。
expando 属性の使用を避ける
拡張属性は DOM 要素に付加される任意の JavaScript 属性であり、メモリ リークを引き起こすことなく拡張属性を使用できますが、このリークのパターンは [ DOM 要素 --> 中間オブジェクト --> DOM 要素を使用する場合は、単純な値型を使用するのが最善の方法です。 Simple タイプを使用し、必要がなくなったら拡張属性を null に設定します。「Internet Explorer のリーク パターンの理解と解決
」の「循環参照」セクションを参照してください。