programing

JavaScript는 객체 속성 순서를 보증합니까?

procenter 2022. 12. 9. 22:21
반응형

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을 몇 가지 공유하다Object는 예외 없이 삽입 순서에 따라 키를 반복할 수 있도록 합니다.

Map의 키는 정렬되지만 객체에 추가된 키는 정렬되지 않습니다.따라서 Map 객체는 반복할 때 삽입 순서대로 키를 반환합니다.(ECMAScript 2015에서는 스펙오브젝트가 문자열 키와 심볼 키의 작성 순서를 유지하므로 문자열 키만 있는 개체를 트래버스하면 삽입 순서대로 키가 생성됩니다.)

참고로 ES2015 이전에는 개체의 속성 순서가 전혀 보장되지 않았습니다.ECMAScript 제3판의 오브젝트 정의(pdf):

4.3.3 오브젝트

개체는 개체 유형의 구성원입니다. 속성에는 원시 값, 개체 또는 함수가 포함되어 있는 무질서한 속성 집합입니다.객체의 속성에 저장된 함수를 메서드라고 합니다.

YES(다만, 반드시 삽입 순서는 아닙니다).

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

  1. 오름차순 정수 키(및 ints로 해석하는 문자열 '1' 등)
  2. 삽입 순서대로 문자열 키(ES2015는 이 키와 모든 브라우저가 준수함을 보장함)
  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이 구현되어 있습니다.Gears를 구현한 후 동등한 HTML5 기능을 도입함으로써 Google도 동일한 작업을 수행합니다.올바른 해결책은 ECMA가 사실상의 표준 동작을 정식으로 스펙의 다음 리비전에 포함시키는 것입니다.

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

, ES5가 ES2015에서도 for-in★★★★★★★★★★★★★★★★」는 다음과 오브젝트를 제시합니다.

const 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. 삽입 순서에 따른 기호

따라서 삽입 순서를 변경할 수 있는 세그먼트가 3개 있습니다(예시와 같음).그리고 정수 같은 키는 삽입 순서에 전혀 구애받지 않습니다.

ES2015에서는 특정 방법만 다음 순서를 따릅니다.

  • Object.assign(Object.assign)
  • Object.defineProperties
  • Object.getOwnPropertyNames
  • Object.getOwnPropertySymbols
  • Reflect.ownKeys
  • JSON.파스
  • JSON.stringify

ES2020에서는 기타 모든 기능(ES2015와 ES2020 사이의 사양에 따라 일부 기능, ES2020의 사양에 따라 다름)이 있으며, 다음과 같은 기능이 있습니다.

  • Object.keys, Object.entries, Object.values, ...
  • ~에 대해서

은 '아까운'이었습니다.for-in고유하게 상속된 속성을 포함하기 때문입니다.는 ES2020에서 (엣지 케이스를 제외한 모든 경우) 수행되었습니다.링크된(완료된) 프로포절의 다음 목록은 순서가 지정되지 않은 에지 케이스를 제공합니다.

  • 반복 중인 개체나 프로토타입 체인의 어떤 개체도 프록시, 유형 배열, 모듈 네임스페이스 개체 또는 호스트 외래 개체가 아닙니다.
  • 개체나 프로토타입 체인의 어떤 것도 반복 중에 프로토타입이 변경되지 않습니다.
  • 개체나 프로토타입 체인의 어떤 것도 반복 중에 삭제된 속성을 가지고 있지 않습니다.
  • 개체의 프로토타입 체인에 반복 중에 추가된 속성이 없습니다.
  • 반복하는 동안 개체 또는 프로토타입 체인에 있는 개체의 속성이 열거 가능성에 변경되지 않았습니다.
  • 헤아릴 수 없는 속성은 헤아릴 수 없는 속성입니다.

결론:ES2015에서도 JavaScript에서 일반 객체의 속성 순서에 의존해서는 안 됩니다.오류가 발생하기 쉽습니다.순서부여된 이름부 쌍이 필요한 경우 대신 을 사용하십시오.이 경우 삽입 순서는 순수하게 사용됩니다.순서만 필요한 경우 어레이 또는 (순수 삽입 순서도 사용)를 사용합니다.

글을 쓸 당시 대부분의 브라우저는 삽입된 것과 같은 순서로 속성을 반환했지만, 동작이 보증되지 않았기 때문에 신뢰해서는 안 됩니다.

ECMAScript 사양은 다음과 같이 기술되어 있습니다.

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

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

이 모든 답변은 사양 준수에 관한 것이지 특정 시점이나 과거의 엔진에서 수행한 작업이 아닙니다.

일반적으로는 아닙니다.

실제 질문은 매우 모호하다.

속성을 추가한 순서와 같게 할 수 있습니까?

어떤 맥락에서요?

정답은 다음과 같습니다. 그것은 많은 요인에 따라 다릅니다.일반적으로, 아니다.

때때로, 네.

서는 플레인 키 를 기대할 수 .Objects:

  • ES2015 준거 엔진
  • 소유 속성
  • Object.getOwnPropertyNames(),Reflect.ownKeys(),Object.getOwnPropertySymbols(O)

모든 , 할 수 와 순서 됩니다.[[OwnPropertyKeys]](일부러) 값은되는 키 ( 「 「」 「」 「」).String //는Symbol이 문맥에서는, 「」를 참조해 주세요.String에는 정수값이 포함됩니다.

Object.getOwnPropertyNames(O)

O님 'String- 키 속성(: 이름).

Reflect.ownKeys(O)

O님 'String - 아, 네~Symbol- 키 - 키 속성. - 키 속성.

Object.getOwnPropertySymbols(O)

O님 'Symbol- 키 - 키 속성. - 키 속성.

[[OwnPropertyKeys]]

와 같은 것이다.Strings, 비오름차순,Strings작성 순서대로 심볼이 작성 순서대로 표시됩니다.이를 호출하는 함수에 따라 이러한 유형의 일부가 포함되지 않을 수 있습니다.

구체적인 언어는 키가 다음 순서로 반환된다는 것입니다.

  1. 속성 키...각 속성 키PO인 [be repeated]는 순서입니다

  2. 속성 키...각 속성 키PO이지만 정수 인덱스가 아닌 속성 creation orderString으로 합니다.

  3. 속성 키...각 속성 키PO은 속성 생성 기호입니다.

Map

, 이 맵을 .Map ES2015 된 유형Objects.

ES2015부터는 속성을 반복하는 특정 메서드에 대해 속성 순서가 보장됩니다.다른 사람은 안 요.유감스럽게도 순서가 보장되지 않는 방법이 일반적으로 가장 자주 사용됩니다.

  • Object.keys,Object.values,Object.entries
  • for..in 스루프
  • JSON.stringify

단, ES20에서 이들 이전에는 신뢰할 수 없었던 방법속성 질서는 완성제안(for-in mechanics) 때문에 다른 방법과 같은 결정론적 방법으로 반복되는 사양에 의해 보증됩니다.

예: " " " " )과 같은 )과 같습니다.Reflect.ownKeys ★★★★★★★★★★★★★★★★★」Object.getOwnPropertyNames이전에 지정되지 않은 메서드도 다음 순서로 반복됩니다.

  • 오름차순 숫자 배열 키
  • 다른 모든 비심볼 키(삽입 순서)
  • 삽입 순서에 따른 기호 키

이것은, 모든 실장이 이미(그리고 오랜 세월에 걸쳐 행해져 온) 거의 모든 실장이 행하고 있는 것입니다.그러나, 새로운 제안으로 인해, 공식화되었습니다.

현재 사양은 다음과 같습니다."거의 완전히 지정되지 않은 실제 엔진은 더 일관된 경향이 있습니다."

ECMA-262의 특이성 결여는 현실을 반영하지 못한다.몇 년 전 논의에서 구현자들은 웹에서 코드를 실행하려는 모든 사용자가 따라야 하는 for-in 동작에 몇 가지 제약이 있다는 것을 알게 되었습니다.

모든 구현은 이미 예측 가능한 속성으로 반복되므로 하위 호환성을 유지하면서 사양에 포함될 수 있습니다.


현재 구현에 동의하지 않는 몇 가지 이상한 경우가 있으며, 이 경우 그 순서는 계속 명시되지 않습니다.자산 순서가 보장되는 경우:

반복 중인 개체나 프로토타입 체인의 어떤 개체도 프록시, 유형 배열, 모듈 네임스페이스 개체 또는 호스트 외래 개체가 아닙니다.

개체나 프로토타입 체인의 어떤 것도 반복 중에 프로토타입이 변경되지 않습니다.

개체나 프로토타입 체인의 어떤 것도 반복 중에 삭제된 속성을 가지고 있지 않습니다.

개체의 프로토타입 체인에 반복 중에 추가된 속성이 없습니다.

반복하는 동안 개체 또는 프로토타입 체인에 있는 개체의 속성이 열거 가능성에 변경되지 않았습니다.

헤아릴 수 없는 속성은 헤아릴 수 없는 속성입니다.

에서는 「」를 할 수 .Map오브젝트 대신 데이터 구조

Developer Mozilla > 맵

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

ES2015에서는 가능하지만, 생각과는 다릅니다.

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

단, ES2015에서는 in이 지정되었습니다.JavaScript의 많은 것들과 마찬가지로, 이것은 호환성을 목적으로 이루어졌으며 일반적으로 대부분의 JS 엔진에서 기존의 비공식 표준을 반영했습니다(누가 예외인지 제외).

이 순서는 오브젝트 자신의 키를 통해 반복하는 모든 메서드를 기반으로 하는 추상 작업인 NormalOwnPropertyKeys 아래에서 사양에 정의되어 있습니다.바꿔 말하면, 순서는 다음과 같습니다.

  1. 모든 정수 인덱스 키(예:"1123","55" ㄴ)ㄹ 수 있습니다.

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

  3. 작성 순서(오래된 것부터 순서대로)의 모든 기호 키.

주문이 신뢰할 수 없다고 하는 것은 어리석은 일입니다.신뢰성이 높고, 아마 당신이 원하는 것이 아닐 것입니다.그리고 최신 브라우저는 이 주문을 올바르게 구현하고 있습니다.

키를 예: " " )이 .for .. in루우프.for .. in루프는 사양에 따른 순서를 보증하지 않습니다.

다른 사람이 말했듯이, 개체의 속성을 반복할 때 순서에 대한 보장은 없습니다.여러 필드의 정렬 목록이 필요한 경우 개체 배열을 만들 것을 제안합니다.

var myarr = [{somfield1: 'x', somefield2: 'y'},
{somfield1: 'a', somefield2: 'b'},
{somfield1: 'i', somefield2: 'j'}];

이렇게 하면 일반 for 루프를 사용하여 삽입 순서를 지정할 수 있습니다.그런 다음 필요에 따라 배열 정렬 방법을 사용하여 새 배열로 정렬할 수 있습니다.

힘들게 알아냈을 뿐이야.

Respect with Redx를 사용하면 저장소를 변경할 때마다(Redx의 불변성 개념에 따라) 하위 항목을 생성하기 위해 이동하려는 키 상태 컨테이너가 새로 고쳐집니다.

「 」를 , 「 」를 취득합니다.Object.keys(valueFromStore)하였습니다.Object.keys(valueFromStore).sort()그러면 적어도 키의 알파벳 순서는 얻을 수 있습니다.

예를 들어 오브젝트와 MAP의 주요 차이점:

OBJECT에서는 그렇지 않은 반면, Map에서는 작성 중에 설정된 순서를 따릅니다.

참조: 오브젝트

const obj = {};
obj.prop1 = "Foo";
obj.prop2 = "Bar";
obj['1'] = "day";
console.log(obj)

**OUTPUT: {1: "day", prop1: "Foo", prop2: "Bar"}**

    const myMap = new Map()
    // setting the values
    myMap.set("foo", "value associated with 'a string'")
    myMap.set("Bar", 'value associated with keyObj')
    myMap.set("1", 'value associated with keyFunc')

OUTPUT:
**1.    ▶0: Array[2]
1.   0: "foo"
2.   1: "value associated with 'a string'"
2.  ▶1: Array[2]
1.   0: "Bar"
2.   1: "value associated with keyObj"
3.  ▶2: Array[2]
1.   0: "1"
2.   1: "value associated with keyFunc"**

100% 페일 세이프 솔루션에서는 네스트된 개체를 사용하여 다음과 같은 작업을 수행할 수 있습니다.

const obj = {};
obj.prop1 = {content: "Foo", index: 0};
obj.prop2 = {content: "Bar", index: 1};

for (let i = 0; i < Object.keys(obj).length; i++)
for (const prop in obj) {
    if (obj[prop].index == i) {
        console.log(obj[prop].content);
        break;
    }
}

JSON 표준에서:

개체는 0개 이상의 이름/값 쌍의 순서가 없는 집합입니다. 여기서 name은 문자열이고 value는 문자열, number, boolean, null, object 또는 배열입니다.

(내 것이 아닌)

그래서 당신은 주문을 보장할 수 없습니다.

언급URL : https://stackoverflow.com/questions/5525795/does-javascript-guarantee-object-property-order

반응형