[javascript] “for (… in…)”루프의 요소 순서

Javascript의 “for… in”루프는 해시 테이블 / 요소를 선언 된 순서대로 반복합니까? 순서대로하지 않는 브라우저가 있습니까?
사용하려는 객체가 한 번 선언 되고 수정되지 않습니다.

내가 가지고 있다고 가정 해보십시오.

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를 제외한 모든 브라우저는 정의 순서 따릅니다. 이 두 브라우저에서 속성은 숫자가 아닌 첫 번째 속성보다 순서대로 가져옵니다 (배열을 구현하는 방법과 관련이 있음). 순서도 동일 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, 노드 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 절 ( “객체”의 정의) :

순서가없는 속성 모음으로 각각 기본 값, 객체 또는 함수를 포함합니다. 객체의 속성에 저장된 함수를 메서드라고합니다.

JavaScript 구현에서 일관된 순서로 열거되는 속성에 의존 할 수 없다는 것을 의미합니다. (어쨌든 언어의 구현 별 세부 사항에 의존하는 것은 나쁜 스타일입니다.)

주문을 정의하려면 객체에 액세스하기 전에 정렬하는 키 배열과 같이 주문을 정의하는 것을 구현해야합니다.


답변

for / in 열거하는 객체의 요소는 DontEnum 플래그가 설정되지 않은 속성입니다. ECMAScript (일명 Javascript) 표준은 명시 적으로 “객체는 정렬되지 않은 속성 모음”입니다 ( 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
}

http://code.google.com/p/v8/issues/detail?id=164 에서 논의 가 표시 되는 경우 반복 순서를 수정하기 위해 사양을 변경하려는 욕구는 개발자들 사이에서 매우 인기있는 욕구처럼 보입니다 .


답변

IE6에서는 순서가 보장되지 않습니다.


답변

주문을 신뢰할 수 없습니다. 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를 보여줍니다.