“ for(… in…)”の要素の順序ループ
-
07-07-2019 - |
質問
" for… in"を実行しますハッシュテーブル/要素を宣言された順にJavaScriptループでループしますか?順番に実行しないブラウザはありますか?
使用したいオブジェクトは 1回と宣言され、変更されることはありません。
私が持っていると仮定します:
var myObject = { A: "Hello", B: "World" };
そして、私はそれらを以下でさらに使用します:
for (var item in myObject) alert(item + " : " + myObject[item]);
「A:" Hello"」を期待できますか常に「B:" World"」の前に来るほとんどの適切なブラウザで?
解決
現在、すべての主要なブラウザは、オブジェクトのプロパティを次の順序でループします。 それらが定義されました。いくつかの場合を除き、Chromeもこれを行います。 [...] この動作は、ECMAScript仕様では明示的に未定義のままです。 ECMA-262のセクション12.6.4:
プロパティを列挙するメカニズムは...実装に依存します。
ただし、仕様は実装とはまったく異なります。すべての最新の実装 ECMAScriptのオブジェクトプロパティが定義された順序で繰り返し処理されます。 このため、Chromeチームはこれをバグと見なしており、修正する予定です。
すべてのブラウザは、定義の順序を尊重します Chromeを除くそして、すべての非数値プロパティ名に対して行うOpera。これらの2つのブラウザでは、プロパティは最初の非数値プロパティの前に順番にプルされます(これは、配列の実装方法に関係しています)。 Object.keys
の順序も同じです。
この例により、何が起こるかが明確になります:
var obj = {
"first":"first",
"2":"2",
"34":"34",
"1":"1",
"second":"second"
};
for (var i in obj) { console.log(i); };
// Order listed:
// "1"
// "2"
// "34"
// "first"
// "second"
この技術は、いつでも変更される可能性があるという事実よりも重要ではありません。このようにしておくことに頼らないでください。
要するに:順序が重要な場合は配列を使用します。
他のヒント
1年後にこれをバンプ...
2012 であり、主要なブラウザはまだ異なります:
function lineate(obj){
var arr = [], i;
for (i in obj) arr.push([i,obj[i]].join(':'));
console.log(arr);
}
var obj = { a:1, b:2, c:3, "123":'xyz' };
/* log1 */ lineate(obj);
obj.a = 4;
/* log2 */ lineate(obj);
delete obj.a;
obj.a = 4;
/* log3 */ lineate(obj);
Safari 5、Firefox 14
["a:1", "b:2", "c:3", "123:xyz"]
["a:4", "b:2", "c:3", "123:xyz"]
["b:2", "c:3", "123:xyz", "a:4"]
Chrome 21、Opera 12、Node 0.6、Firefox 27
["123:xyz", "a:1", "b:2", "c:3"]
["123:xyz", "a:4", "b:2", "c:3"]
["123:xyz", "b:2", "c:3", "a:4"]
IE9
[123:xyz,a:1,b:2,c:3]
[123:xyz,a:4,b:2,c:3]
[123:xyz,a:4,b:2,c:3]
ECMAScript言語仕様から、セクション12.6.4( for .. in
ループ上):
プロパティを列挙するメカニズムは実装に依存します。列挙の順序はオブジェクトによって定義されます。
セクション4.3.3(" Object"の定義):
これは、それぞれがプリミティブな値、オブジェクト、または関数を含むプロパティの順序付けられていないコレクションです。オブジェクトのプロパティに保存されている関数はメソッドと呼ばれます。
これは、JavaScript実装全体で一貫した順序で列挙されているプロパティに依存できないことを意味します。 (とにかく、言語の実装固有の詳細に依存するのは悪いスタイルでしょう。)
順序を定義する場合は、オブジェクトにアクセスする前にソートするキーの配列など、順序を定義するものを実装する必要があります。
列挙/列挙するオブジェクトの要素は、DontEnumフラグが設定されていないプロパティです。 Javaスクリプトとも呼ばれるECMAScript標準では、「オブジェクトはプロパティの順序付けられていないコレクション」と明示的に述べられています。 ( http://www.mozilla.org/js/language/E262-3を参照してください。 .pdf セクション8.6)。
すべてのJavascript実装が宣言順に列挙されると想定することは、標準に準拠する(つまり安全ではない)
反復順序もプロパティの削除に関して混乱していますが、この場合はIEのみです。
var obj = {};
obj.a = 'a';
obj.b = 'b';
obj.c = 'c';
// IE allows the value to be deleted...
delete obj.b;
// ...but remembers the old position if it is added back later
obj.b = 'bb';
for (var p in obj) {
alert(obj[p]); // in IE, will be a, bb, then c;
// not a, c, then bb as for FF/Chrome/Opera/Safari
}
注文は信頼できません。 OperaとChromeの両方が、プロパティのリストを順不同で返します。
<script type="text/javascript">
var username = {"14719":"A","648":"B","15185":"C"};
for (var i in username) {
window.alert(i + ' => ' + username[i]);
}
</script>
上記のコードは、OperaでB、A、C、ChromeでC、A、Bを示しています。
これは質問自体には答えませんが、基本的な問題の解決策を提供します。
保存する順序に依存できないと仮定して、プロパティとしてキーと値を持つオブジェクトの配列を使用しないのはなぜですか?
var myArray = [
{
'key' : 'key1'
'value' : 0
},
{
'key' : 'key2',
'value' : 1
} // ...
];
今、キーが一意であることを確認するのはあなた次第です(これもあなたにとって重要であると仮定します。同様に、直接アドレス指定の変更、for(... in ...)はインデックスを 'キー」。
> console.log(myArray[0].key);
key1
> for (let index in myArray) {console.log(myArray[index].value);}
0
1
JDQによる(... in ...)順番のアドレス指定については、ペンを参照してください( @JDQ ) CodePen 。