まず第一に、JavaScript で利用できるデータ構造について、根本的な混乱があります。
TL;DR
短いプロトタイプ継承チェーンを持つオブジェクトのキー検索を最速にしたい場合は、 を使用しますin
。
同じことが必要であるが、広範な継承チェーンを持つオブジェクトの場合は、使用しますObject.prototype.hasOwnProperty
最速の値ルックアップが必要な場合は、 for を使用Array.prototype.indexOf
しArray
ます。
ハッシュ テーブルの値を検索するための組み込み関数はありません。もちろん、独自のものを作成することもできますが、既に提供しているライブラリが多数あります。たとえば、Underscore は 1 つを提供します (これを と呼びますindexOf
)。
JavaScript には配列がありません
基本的に、JavaScript にはハッシュ テーブルしかありません。標準関数は、キーが文字列キーに加えて整数であるハッシュ テーブル (これらを整数 hash-tablesまたはint-hash-tablesArray
と呼びます) を構築します。これらは配列と同様に機能しますが、特定の点で異なります。短所と長所があります。たとえば、int-hash-table から要素を削除するのは O(1) 操作ですが、配列から要素を削除するのは O(n) 操作です (残りの要素を新しい配列にコピーする必要があるため)。これが、JavaScript の関数が非常に高速である理由です。欠点は、実装の複雑さです。Array.prototype.splice
そのため、JavaScript のコンテキストで言うとArray
、int-hash-table として理解され、それに関連するすべての漸近的な複雑さが生じます。これは、int-hash-table 内で文字列値を検索する場合、O(n) 操作になることを意味します。それを行うための標準関数があります: Array.prototype.indexOf
. ただし、キーを探したい場合は、と の2 つの関数がin
ありObject.prototype.hasOwnProperty
ます。
やや直感に反する:
[1, 2, 3].hasOwnProperty(0); // true
0 in [1, 2, 3]; // true
この 2 つの違いについては、さらに説明する必要があります。これは、JavaScript のすべてのものはオブジェクトであり、オブジェクトのような機能を備えているという事実に関連しています。そのような機能の 1 つはprototype
、オブジェクトとそのプロトタイプの間のリンクです。これは、オブジェクトのプロパティを含むハッシュ テーブルの階層構造です。
JavaScript は動的な性質を持っているため、すべての関数呼び出しは動的であり、フェイル セーフなコード実行を確実にするために、環境は細心の注意を払う必要があります。これは、JavaScript 関数呼び出しが非常に高価であることを意味します。したがって、理論的には逆になるはずですが、通過する方が通過Object.prototype.hasOwnProperty
するよりもはるかに費用がかかる可能性があります。in
ただし、十分な高さの継承ツリーと十分な継承プロパティがあれば、最終的にObject.prototype.hasOwnProperty
は引き継がれます。
より良い直感を得るためのいくつかの例:
>>> var array = [1, 2, 3];
undefined
>>> 3 in array;
false
>>> array.hasOwnProperty(3);
false
>>> 3 in array;
false
>>> array.__proto__ = [1, 2, 3, 4];
[1, 2, 3, 4]
>>> 3 in array;
true
>>> array.hasOwnProperty(3);
false