your programing

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

lovepro 2020. 10. 3. 11:27
반응형

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의 키는 정렬되지만 객체에 추가 된 키는 정렬되지 않습니다. 따라서 반복 할 때 Map 객체는 삽입 순서대로 키를 반환합니다. (ECMAScript 2015 사양에서 객체는 문자열 및 기호 키의 생성 순서를 유지하므로 문자열 키만있는 객체를 순회하면 삽입 순서대로 키가 생성됩니다)

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

4.3.3 개체

개체는 개체 유형의 구성원입니다. 이는 각각 원시 값, 객체 또는 함수를 포함 하는 순서없는 속성 모음입니다 . 객체의 속성에 저장된 함수를 메서드라고합니다.


예 (정수가 아닌 키의 경우)-위의 대답은 잘못되었습니다!

현재 언어 사양 (ES2015 이후) 삽입 순서는 유지됩니다. 단, 정수로 구문 분석하는 키 (예 : "7"또는 "99")의 경우를 제외하고 브라우저마다 동작이 다릅니다. 예를 들어 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
  • Reflect.ownKeys

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

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

Conclusion: Even in ES2015 you shouldn't rely on the property order of normal objects in Javascript. It is prone to errors. Use Map instead.


At the time of writing, most browsers did return properties in the same order as they were inserted, but it was explicitly not guaranteed behaviour so shouldn't have been relied upon.

The ECMAScript specification used to say:

The mechanics and order of enumerating the properties ... is not specified.

However in ES2015 and later non-integer keys will be returned in insertion order.


This whole answer is in the context of spec compliance, not what any engine does at a particular moment or historically.

Generally, no

The actual question is very vague.

will the properties be in the same order that I added them

In what context?

The answer is: it depends on a number of factors. In general, no.

Sometimes, yes

Here is where you can count on property key order for plain Objects:

  • ES2015 compliant engine
  • Own properties
  • Object.getOwnPropertyNames(), Reflect.ownKeys(), Object.getOwnPropertySymbols(O)

In all cases these methods include non-enumerable property keys and order keys as specified by [[OwnPropertyKeys]] (see below). They differ in the type of key values they include (String and / or Symbol). In this context String includes integer values.

Object.getOwnPropertyNames(O)

Returns O's own String-keyed properties (property names).

Reflect.ownKeys(O)

Returns O's own String- and Symbol-keyed properties.

Object.getOwnPropertySymbols(O)

Returns O's own Symbol-keyed properties.

[[OwnPropertyKeys]]

The order is essentially: integer-like Strings in ascending order, non-integer-like Strings in creation order, Symbols in creation order. Depending which function invokes this, some of these types may not be included.

The specific language is that keys are returned in the following order:

  1. ... each own property key P of O [the object being iterated] that is an integer index, in ascending numeric index order

  2. ... each own property key P of O that is a String but is not an integer index, in property creation order

  3. ... each own property key P of O that is a Symbol, in property creation order

Map

If you're interested in ordered maps you should consider using the Map type introduced in ES2015 instead of plain Objects.


In modern browsers you can use the Map data structure instead of a object.

Developer mozilla > Map

A Map object can iterate its elements in insertion order...


In ES2015, it does, but not to what you might think

The order of keys in an object wasn't guaranteed until ES2015. It was implementation-defined.

However, in ES2015 in was specified. Like many things in JavaScript, this was done for compatibility purposes and generally reflected an existing unofficial standard among most JS engines (with you-know-who being an exception).

The order is defined in the spec, under the abstract operation OrdinaryOwnPropertyKeys, which underpins all methods of iterating over an object's own keys. Paraphrased, the order is as follows:

  1. All integer index keys (stuff like "1123", "55", etc) in ascending numeric order.

  2. All string keys which are not integer indices, in order of creation (oldest-first).

  3. All symbol keys, in order of creation (oldest-first).

It's silly to say that the order is unreliable - it is reliable, it's just probably not what you want, and modern browsers implement this order correctly.

Some exceptions include methods of enumerating inherited keys, such as the for .. in loop. The for .. in loop doesn't guarantee order according to the specification.


As others have stated, you have no guarantee as to the order when you iterate over the properties of an object. If you need an ordered list of multiple fields I suggested creating an array of objects.

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

This way you can use a regular for loop and have the insert order. You could then use the Array sort method to sort this into a new array if needed.


Just found this out the hard way.

Using React with Redux, the state container of which's keys I want to traverse in order to generate children is refreshed everytime the store is changed (as per Redux's immutability concepts).

Thus, in order to take Object.keys(valueFromStore) I used Object.keys(valueFromStore).sort(), so that I at least now have an alphabetical order for the keys.


From the JSON standard:

An object is an unordered collection of zero or more name/value pairs, where a name is a string and a value is a string, number, boolean, null, object, or array.

(emphasis mine).

So, no you can't guarantee the order.

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

반응형