[javascript] JavaScript는 객체 속성 순서를 보장합니까?

이런 객체를 만들면 :

var obj = {};
obj.prop1 = "Foo";
obj.prop2 = "Bar";

결과 객체는 항상 이런 모양입니까?

{ prop1 : "Foo", prop2 : "Bar" }

즉, 속성은 내가 추가 한 순서와 동일합니까?



답변

객체의 반복 순서는 ES2015 이후 특정 규칙 세트를 따르지만 항상 삽입 순서를 따르지 않습니다 . 간단히 말해서, 반복 순서는 문자열 키의 삽입 순서와 숫자와 같은 키의 오름차순의 조합입니다.

// key order: 1, foo, bar
const obj = { "foo": "foo", "1": "1", "bar": "bar" }

배열이나 Map객체를 사용하는 것이 더 좋은 방법 일 수 있습니다. Map주 일부 유사점 Object삽입의 순서로 반복되는 키를 보장 예외없이 :

맵에있는 키는 객체에 추가 된 키가 아닌 순서로 정렬됩니다. 따라서 반복 할 때 Map 객체는 삽입 순서대로 키를 반환합니다. (ECMAScript 2015 사양 객체는 문자열 및 심볼 키의 생성 순서를 유지하므로 문자열 키만있는 객체의 순회는 삽입 순서에 따라 키를 생성합니다)

참고로 ES2015 이전에는 객체의 속성 순서가 전혀 보장되지 않았습니다. ECMAScript Third Edition 의 객체 정의 (pdf) :

4.3.3 객체

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


답변

예 (정수가 아닌 키의 경우).

대부분의 브라우저는 다음과 같이 객체 속성을 반복합니다.

  1. 오름차순의 정수 키 (및 int로 구문 분석하는 “1”과 같은 문자열)
  2. 삽입 순서의 문자열 키
  3. 삽입 순서의 기호 이름 (ES2015는이를 준수하며 모든 브라우저는이를 준수 함)

일부 구형 브라우저는 카테고리 # 1과 # 2를 결합하여 모든 키를 삽입 순서대로 반복합니다. 키가 정수로 구문 분석 될 수있는 경우 특정 반복 순서에 의존하지 않는 것이 가장 좋습니다.

브라우저마다 동작이 달라지는 정수 (예 : “7”또는 “99”)로 구문 분석되는 키의 경우를 제외하고 현재 언어 사양 (ES2015 이후) 삽입 순서가 유지됩니다. 예를 들어, 키가 숫자로 구문 분석 될 때 Chrome / V8은 삽입 순서를 고려하지 않습니다.

이전 언어 사양 (ES2015 이전) : 반복 순서는 기술적으로 정의되지 않았지만 모든 주요 브라우저는 ES2015 동작을 준수했습니다.

ES2015 동작은 기존 동작에 의해 구동되는 언어 사양의 좋은 예이며 다른 방식은 아닙니다. 이전 버전과의 호환성에 대한 심도를 더 깊이 이해하려면 Chrome의 반복 순서 동작에 대한 디자인 결정을 자세히 설명하는 Chrome 버그 인 http://code.google.com/p/v8/issues/detail?id=164를 참조하십시오 . . 해당 버그 보고서에 대한 (의견이없는) 의견 중 하나에 대해 :

표준은 항상 XHR의 출처 인 구현을 따르며 Google은 Gears를 구현 한 다음 동등한 HTML5 기능을 수용함으로써 동일한 작업을 수행합니다. 올바른 수정은 ECMA가 사실상의 표준 동작을 사양의 다음 개정판에 공식적으로 통합하도록하는 것입니다.


답변

일반 객체의 속성 순서는 Javascript의 복잡한 주제입니다.

ES5에서는 명시 적으로 주문이 지정되어 있지 않지만 ES2015는 특정 주문이 있습니다. 다음과 같은 객체가 주어진다 :

o = Object.create(null, {
  m: {value: function() {}, enumerable: true},
  "2": {value: "2", enumerable: true},
  "b": {value: "b", enumerable: true},
  0: {value: 0, enumerable: true},
  [Symbol()]: {value: "sym", enumerable: true},
  "1": {value: "1", enumerable: true},
  "a": {value: "a", enumerable: true},
});

결과는 다음과 같습니다 (특정 경우).

Object {
  0: 0,
  1: "1",
  2: "2",
  b: "b",
  a: "a",
  m: function() {},
  Symbol(): "sym"
}
  1. 정수형 키 (오름차순)
  2. 삽입 순서의 일반 키
  3. 삽입 순서의 기호

따라서 삽입 순서를 변경할 수있는 세 개의 세그먼트가 있습니다 (예제에서와 같이). 그리고 정수와 같은 키는 삽입 순서에 전혀 영향을 미치지 않습니다.

문제는 ES2015 사양 에서이 순서가 보장되는 방법은 무엇입니까?

다음 방법은 표시된 순서를 보장합니다.

  • Object.assign
  • Object.defineProperties
  • Object.getOwnPropertyNames
  • Object.getOwnPropertySymbols
  • Ref.ownKeys

다음 방법 / 루프는 전혀 순서를 보장하지 않습니다.

  • Object.keys
  • for..in
  • JSON.parse
  • JSON.stringify

결론 : ES2015에서도 Javascript에서 일반 객체의 속성 순서에 의존해서는 안됩니다. 오류가 발생하기 쉽습니다. Map대신 사용하십시오 .


답변

작성 당시 대부분의 브라우저는 삽입 된 순서와 동일한 순서로 속성을 반환했지만 동작이 명시 적으로 보장되지는 않았으므로 의존해서는 안됩니다.

인 ECMAScript 사양은 말을 사용 :

속성을 열거하는 메커니즘과 순서는 지정되어 있지 않습니다.

그러나 ES2015 이상에서는 정수가 아닌 키가 삽입 순서대로 반환됩니다.


답변

이 전체 답변은 특정 순간이나 역사적으로 엔진이하는 것이 아니라 사양 준수의 맥락에 있습니다.

일반적으로

실제 질문은 매우 모호합니다.

속성을 내가 추가 한 순서와 동일하게

어떤 맥락에서?

답은 여러 가지 요소에 따라 다릅니다. 일반적으로, 전혀 .

어쩔 땐 그래

다음은 평범한 속성 키 순서를 신뢰할 수있는 위치입니다 Objects.

  • ES2015 호환 엔진
  • 자신의 속성
  • Object.getOwnPropertyNames(), Reflect.ownKeys(),Object.getOwnPropertySymbols(O)

모든 경우에 이러한 방법에는 열거 할 수없는 속성 키와 주문 키가 포함됩니다 [[OwnPropertyKeys]](아래 참조). 포함하는 키 값의 유형 ( String및 / 또는 Symbol) 이 다릅니다 . 이와 관련하여 String정수 값 이 포함됩니다.

Object.getOwnPropertyNames(O)

O자체 String키 속성 ( 속성 이름 )을 반환 합니다.

Reflect.ownKeys(O)

O자체 StringSymbol키 속성을 반환 합니다.

Object.getOwnPropertySymbols(O)

O자체 Symbol키 속성을 반환 합니다.

[[OwnPropertyKeys]]

순서는 본질적 Strings으로 오름차순의 정수와 같고 Strings, 생성 순서의 정수와 같지 않고 , 생성 순서의 기호 와 같습니다 . 이를 호출하는 함수에 따라 이러한 유형 중 일부는 포함되지 않을 수 있습니다.

특정 언어는 키가 다음 순서로 반환된다는 것입니다.

  1. … 정수 색인 PO[반복되는 객체] 의 고유 한 속성 키 , 숫자 인덱스 순서 오름차순

  2. … 각각 자신의 속성 키 PO그 문자열하지만 속성 생성하기, 정수 인덱스가 아닙니다

  3. … 각 고유의 속성 키 PO속성 생성 순서에서 기호입니다.

Map

정렬 된 맵에 관심이있는 경우 Mapplain 대신 ES2015에 도입 된 유형을 사용하는 것이 좋습니다 Objects.


답변

최신 브라우저에서는 Map객체 대신 데이터 구조를 사용할 수 있습니다 .

개발자 mozilla>지도

Map 객체는 삽입 순서대로 요소를 반복 할 수 있습니다 …


답변

ES2015에서는 생각하지만 그렇게 생각하지 않습니다

ES2015까지는 객체의 키 순서가 보장되지 않았습니다. 구현 정의되었습니다.

그러나, ES2015의에 있었다 지정되었습니다. JavaScript의 많은 것들과 마찬가지로, 이것은 호환성을 목적으로 수행되었으며 일반적으로 대부분의 JS 엔진에있는 기존의 비공식 표준을 반영합니다 (예외를 아는 사람).

순서는 추상 조작 OrdinaryOwnPropertyKeys 아래의 스펙에 정의되어 오브젝트 자체의 키를 반복하는 모든 메소드를 뒷받침합니다. 해석하면 순서는 다음과 같습니다.

  1. 모두 정수 인덱스 키 (같은 물건 "1123", "55"숫자 오름차순으로, 등).

  2. 생성 순서대로 정수 인덱스가 아닌 모든 문자열 키 (가장 오래된 것부터).

  3. 생성 순서에 따른 모든 기호 키 (가장 오래된 것부터).

순서가 신뢰할 수 없다고 말하는 것은 어리석은 일입니다. 신뢰할 수 있고, 아마도 원하는 것이 아니며, 최신 브라우저는이 순서를 올바르게 구현합니다.

일부 예외는 for .. in루프 와 같은 상속 된 키를 열거하는 방법을 포함합니다 . for .. in루프는 사양에 따라 순서를 보장하지 않습니다.