[解決済み] arr = new Arrayよりarr = []の方が速いのはなぜですか?
質問
このコードを実行したところ、以下のような結果が得られました。なぜ
[]
の方が速いのですか?
console.time('using[]')
for(var i=0; i<200000; i++){var arr = []};
console.timeEnd('using[]')
console.time('using new')
for(var i=0; i<200000; i++){var arr = new Array};
console.timeEnd('using new')
-
使用
[]
: 299ms -
使用
new
: 363ms
感謝 レイノス はこちらです。 ベンチマーク このコードと、変数を定義するためのいくつかの可能な方法を示します。
解決方法は?
これまでの回答をさらに発展させると...
一般的なコンパイラの観点から、VM 固有の最適化を無視した場合。
まず、字句解析の段階で、コードをトークン化する。
例として、以下のようなトークンが生成されることがある。
[]: ARRAY_INIT
[1]: ARRAY_INIT (NUMBER)
[1, foo]: ARRAY_INIT (NUMBER, IDENTIFIER)
new Array: NEW, IDENTIFIER
new Array(): NEW, IDENTIFIER, CALL
new Array(5): NEW, IDENTIFIER, CALL (NUMBER)
new Array(5,4): NEW, IDENTIFIER, CALL (NUMBER, NUMBER)
new Array(5, foo): NEW, IDENTIFIER, CALL (NUMBER, IDENTIFIER)
これで、どの程度の処理が必要なのか、十分に視覚化できるようになったのではないでしょうか。
-
上記のトークンから、ARRAY_INITは常に配列を生成することが事実として分かっています。 したがって、単純に配列を作成し、それに値を入れるだけです。 曖昧さに関しては、字句解析の段階ですでにARRAY_INITとオブジェクトのプロパティアクセサ(例えば
obj[foo]
や、文字列/正規表現内の括弧("foo[]bar" や /[]/ など)です。) -
これは微々たるものですが、さらにトークンを
new Array
. さらに、単に配列を作りたいだけなのか、まだ完全に明確ではありません。 new"トークンがありますが、new"とは何でしょうか? IDENTIFIER トークンは、新しい "Array を作成することを意味しますが、JavaScript VM は通常、IDENTIFIER トークンと "native global objects." のトークンを区別しません。 -
IDENTIFIER トークンに遭遇するたびに、スコープ チェーンを調べなければなりません。 Javascript VM には、各実行コンテキストに対して、quot;arguments" オブジェクトやローカル定義の変数などを含む Activation object" が含まれています。 もし、Activationオブジェクトの中に見つからない場合は、グローバルスコープに到達するまで、スコープチェーンを検索し始めます。 もし、何も見つからなければ
ReferenceError
. -
変数宣言の場所を決めたら、コンストラクタを呼び出します。
new Array
は暗黙の関数呼び出しで、関数呼び出しは実行時に遅くなるという経験則があります (静的 C/C++ コンパイラが "function inlining" を許すのはそのためで、JS JIT エンジンでは SpiderMonkey などはその場で処理しなければなりません)。 -
その
Array
コンストラクタはオーバーロードされています。 Array コンストラクタはネイティブコードとして実装されているため、パフォーマンスが向上していますが、引数の長さをチェックして、それに応じて動作する必要があります。 new Array("foo") は ["foo"] を生成し、一方 new Array(1) は [undefined] を生成します。
つまり、配列リテラルを使用すると、VMは配列が必要であることを認識します。
new Array
を理解するために余分な CPU サイクルを使う必要があります。
new Array
実際に
が行います。
関連
-
jsを使った簡単な照明スイッチのコード
-
[解決済み】ローカルファイルを開くことができません - Chrome: ローカルリソースの読み込みが許可されていない
-
[解決済み】「X-Frame-Options」を「SAMEORIGIN」に設定したため、フレームでの表示を拒否された。
-
[解決済み] 配列から特定の項目を削除するにはどうすればよいですか?
-
[解決済み] なぜGoogleはJSONレスポンスにwhile(1);を前置するのでしょうか?
-
[解決済み] SQLiteのINSERT/per-secondのパフォーマンスを向上させる
-
[解決済み] B "の印刷が "#"の印刷より劇的に遅いのはなぜですか?
-
[解決済み] 要素ごとの加算は、結合ループよりも分離ループの方がはるかに高速なのはなぜですか?
-
[解決済み] <は<=より速いのか?
-
[解決済み] Intel CPU の _mm_popcnt_u64 で、32 ビットのループカウンターを 64 ビットに置き換えると、パフォーマンスが著しく低下します。
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Vue Element-uiは、アイコンを追加するためのツリーコントロールノードを詳細に実装しています。
-
Vueの要素ツリーコントロールに破線を追加する説明
-
jQueryのコピーオブジェクトの説明
-
[解決済み】ローカルファイルを開くことができません - Chrome: ローカルリソースの読み込みが許可されていない
-
[解決済み] 配列の結合時に未定義のプロパティ 'push' を読み込むことができない
-
[解決済み】JavaScriptの配列でforEachが関数でない不具合
-
フロントエンド null のプロパティ 'disabled' を読み取れない 問題が解決された
-
[解決済み] JavaScriptの配列宣言で「Array()」と「[]」はどう違うのですか?
-
[解決済み】ループ内でオブジェクトリテラルの配列を作成する方法は?
-
[解決済み】new Object()`とオブジェクトリテラル記法の違いは何ですか?