配列のキー番号"数"では、意外にもと同じ
-
19-08-2019 - |
質問
んjavascriptの配列として、何を感じ、矛盾もいいので説明しています。
で始ます:
var myArray = [1, 2, 3, 4, 5];
document.write("Length: " + myArray.length + "<br />");
for( var i in myArray){
document.write( "myArray[" + i + "] = " + myArray[i] + "<br />");
}
document.write(myArray.join(", ") + "<br /><br />");
Length: 5 myArray[0] = 1 myArray[1] = 2 myArray[2] = 3 myArray[3] = 4 myArray[4] = 5 1, 2, 3, 4, 5
いていかなければなりませんこのコードが理解しているjavascriptの配列がオブジェクトでproperitiesする追加の配列は、これらのproperitiesに追加される配列のよう矛盾した。
続ける前に、どのよう注文字列値に変換できる数値です。
空でない文字列->数値の文字列またはNaN
空の文字列->0
でインストールし、javascriptの配列がオブジェクトの法:
myArray["someThing"] = "someThing";
myArray[""] = "Empty String";
myArray["4"] = "four";
(var i myArray){
書きします。write("myArray["+i+"]="+myArray[i]+"<br />");}
書きします。write(myArray.join(",")+"<br /><br />");
Length: 5 myArray[0] = 1 myArray[1] = 2 myArray[2] = 3 myArray[3] = 4 myArray[4] = four myArray[someThing] = someThing myArray[] = Empty String 1, 2, 3, 4, four
出力は予想外でした。
に空文字列を"4"に変換され、その数値を設定する場合にmyArray["4"],このようだ。しかし、空の文字列""がなに変換され、その数値を0では空文字列となります。もの以外は空文字列"何か"がなに変換され、その数値、NaN、文字列として扱われます。いるのですか?は、決算内myArray[]内の数値は文字列。
また、されている理由は何でしょうかつ、数字、properitiesのmyArray含まれませんmyArray.長myArray.join(",")?
解決
JavaScriptの配列のキーは、実際には文字列です。詳細および任意のキーのマップタイプの実装では、この回答する を確認します。
<時間>明確にし、ジェイソンは掲載内容に追加するには:JavaScriptの配列はオブジェクトです。オブジェクトは、プロパティを持っています。プロパティ名は文字列値です。したがって、配列インデックスは、同様に多くの何かが起こることができる前に、文字列に変換されます。
:プロパティ名Pは、以下の(ECMA-262、15.4)を保持していれば(つまり、特殊な配列-魔法が呼び出される)配列インデックスとして扱われますのToString(ToUint32(P))Pに等しく、ToUint32(P)は2 ^ 32に等しくない - 1
の数値インデックスは列(としない他の方法で回避)に変換されることを容易に確認することができます:
var array = [];
array[1] = 'foo';
array['1'] = 'bar';
array['+1'] = 'baz';
document.writeln(array[1]); // outputs bar
<時間>
また、for..in
ループで配列のエントリを反復処理するためにその悪い習慣 - 誰かがいくつかのプロトタイプでめちゃめちゃ場合は、予期しない結果を得る可能性があります(そして、それは本当に速い、のいずれかではありません)。標準を使用してくださいfor(var i= 0; i < array.length; ++i)
代わります。
他のヒント
(編集:次はかなり右ではありません)。
のJavaScriptのキーのオブジェクトのは、実際には文字列です。それ自体でJavascriptのの配列は数字のインデックスを持っています。あなたは非負の整数として解釈することができ、インデックスで何かを保存する場合、それはそうしようとします。あなたは非負整数でないインデックスに何かを保存する場合(例えば、それは、英数字負だ、または小数部分を持つ浮動小数点数)が、それは、配列インデックスストアに失敗し、のオブジェクトにデフォルトこれらの保存されたプロパティはArrayクラスからは見えないため、その方法/プロパティ(に見えません - [文字列インデックスによってストリングと店舗に引数を変換する(配列の基本クラスである)の店舗、長さ、スライス、スプライス、プッシュ、ポップ、など)に参加。
編集:(クリストファーさんのfoo /バー/バズの例が示すように)上記の非常に適切ではありません。 のECMAScript仕様のに応じて実際の記憶指数はであり事実、文字列、それらが有効な配列インデックス(非負整数)であるならば、特別な配列オブジェクトの[[Put]]
方法は、配列の「配列っぽい」方法とそれらの特定の値が可視になります。
これはフィロのポストするへの答えです。彼は、オブジェクトのバージョンごとに異なるプロパティ名を使用しているため、彼のベンチマークには欠陥がある:彼は同様ではなく、i
x
使用している必要があります。
このように、たとえば、正しく行われた場合:
var start, end, count = 1000000;
var obj = {},
array = [];
start = new Date;
for(var i = count; i--; )
array[i] = i;
end = new Date;
document.writeln(Number(end) - Number(start));
start = new Date;
for(var i = count; i--; )
obj[i] = i;
end = new Date;
document.writeln(Number(end) - Number(start));
あなたは時間が非常に近くなることがわかります。 FF3.0.5では、配列バージョンは(オペラで、それは周りの他の方法です)でも一貫して遅くなります。
アレイは、JavaScriptで他のすべてのように、オブジェクトです。オブジェクトは、開発者の負担を軽減するために、のドット表記のに恵まれてきました。あなたの例を使用して
myArray["someThing"] = "someThing";
タグを書くことと同じです
myArray.someThing = "someThing";
このケースでは、オブジェクトにプロパティを追加する代わりに、アレイにそれを追加します。同じことは、空の文字列で行くあなたは、空の文字列をのドット表記を使用することはできませんが...奇妙な、ハァッ?
「4」の場合には、整数に強制することができ、したがって、アレイへのインデックスとして使用されます。
私はクリストフに反対ます。
まず、私はそれが実装に依存だと思う...私は(良い)実装がそれを行うには、いくつかのスマートな方法があり、配列アクセスを最適化すると仮定します。
実は、私は少しテストをした、そしてそれは、ほとんどのマイクロベンチマークと同様に良好であるものの、それは面白いです(つまり、超信頼性がありません。):
result = ""
var x;
var trueArray = []
var startTime = new Date();
for (var i = 0; i < 100000; i++)
{
x = "i" + i; // To do the same operations
trueArray[i] = 1;
}
var endTime = new Date();
result += "With array: " + (endTime - startTime) + "\n";
var sArray = []
var startTime = new Date();
for (var i = 0; i < 100000; i++)
{
x = "" + i;
sArray[x] = 1;
}
var endTime = new Date();
result += "With s array: " + (endTime - startTime) + "\n";
var objArray = {}
var startTime = new Date();
for (var i = 0; i < 100000; i++)
{
x = "i" + i;
objArray[x] = 1;
}
var endTime = new Date();
result += "With object(i): " + (endTime - startTime) + "\n";
var sobjArray = {}
var startTime = new Date();
for (var i = 0; i < 100000; i++)
{
x = "" + i;
sobjArray[x] = 1;
}
var endTime = new Date();
result += "With s object: " + (endTime - startTime) + "\n";
var iobjArray = {}
var startTime = new Date();
for (var i = 0; i < 100000; i++)
{
x = "" + i;
iobjArray[i] = 1;
}
var endTime = new Date();
result += "With i object: " + (endTime - startTime) + "\n";
// Then display result
IE6で、私が取得:Arrayで:オブジェクトと1453:3547
を
FF 3.0で、私が取得:Arrayで:オブジェクトと83:226
を
サファリ3.1で、私が取得:Arrayで:オブジェクトと140:313
を
オペラ9.26で、何らかの理由で私は結果を得ることはありませんが、私はループの数の1/10に低減している場合、私が取得:Arrayで:オブジェクトと47:516
実は、私はこれを入力しながら、Operaは実行してみましょう、そして最終的に結果を得た:配列の場合:281オブジェクトの場合:166063 ...
の配列が最適化されるように!これは幸運です...
クリストフのデモンストレーションが私を感動しませんでした。私の結論は、数値として解釈できる文字列は引用符で囲まれた式と一緒に行くこれは、そのように扱われていることをより多くのだろう...
だからあなたの結果の私の解釈は、(スパース値、すなわち上の連想配列のかもしれない行動で。いくつかの孤立大きなインデックス)これらをフィードする場合、配列は、数値インデックスを持つ高速な配列のように動作しているということですが、オブジェクトとして、それはまだ性質の通常の取り扱いを持っています。しかし、これらのプロパティは、アレイ部で処理されていない、あなたが得たので、結果は(参加)。
[EDIT]私はクリストフのアイデア以下、いくつかのループを追加しました。
FF3に、私が得る:アレイと:92の配列:オブジェクト(I)93:Sオブジェクトと243:194私はオブジェクトと:125(パーフの実行の間で変化するが、概ね一致しています)。
私だ、この整数の超納得していない - >列 - >整数往復ではなく、さらにそのECMAリクエストこのシーケンス。私はそれを読み取る方法がある:プロパティが文字列であると、それはそのようなものとして扱われる、整数として解釈することができる
。もちろん、知っている唯一の確実な方法は、実装を見てだろう...
私は、整数の性質または整数に変換することができるプロパティを取得無地のオブジェクトが何らかの形で最適化されて興味を持って注意してください。実装は、このケースを最適化することは興味深いと判断しておそらく、JSプログラマの多くは、配列としてプレーンなオブジェクトを使用しているため。