
요약
좀 다름
들어가는 말
자바스크립트는 온 세상이 객체라고 해도 될 정도이긴 하지만, 객체의 활용법 중 하나는 마치 파이썬의 dictionary처럼 key-value 쌍으로 이루어진 저장소를 사용할 수 있다는 점입니다.
const score = {
korean: 30,
math: 20,
english: 10,
};
이런 식으로요.
여기에서 만약 key 값들만을 원한다면 Object.keys(score)
이런 식으로 가져올 수 있겠죠. 이 때 나오는 배열의 순서는 어떨까요? 크게 세 가지 선택지가 있을 것 같아요.
- 적은 순서대로 나온다.
['korean', 'math', 'english']
- 가나다 순서대로 나온다.
['english', 'korean', 'math']
- 매번 무작위로 섞여서 나온다.
실제 코드를 돌려보면 적은 순서대로 나옵니다. 하지만 이번에만 그런 것이지, '적은 순서대로 나온다'는 말은 틀렸습니다.
const score = {
korean: 30,
math: 20,
english: 10,
1234: 0,
};
console.log(Object.keys(score));
이렇게 살짝 바꾸면 결과는 ['1234', 'korean', 'math', 'english']
입니다. 단순한 시간 순서가 아니라는 말이죠.
실제 규칙
정말 놀랍게도 ECMAScript Spec에는 그 알고리즘이 기술되어 있습니다. 요약하면 크게 세 단계로 나누어지는데요.
- array index 들을 맨 앞에, 오름차순으로 정렬
- array index 가 아닌 String 친구들을 시간 오름차순으로 정렬
- Symbol 들을 시간 오름차순으로 정렬
객체의 key 중 array index 라는 친구들이 먼저 오름차순으로 오고, 그 다음에 문자열은 넣은 순서대로, 마지막으로 심볼들이 넣은 순서대로 오네요.
array index
객체는 배열이 아닌데 array index 라는 건 도대체 뭘 말하는 걸까요? 우선 자바스크립트 객체의 key 값으로는 문자열 또는 심볼만 올 수 있으니 array index 역시 일종의 문자열입니다. 위쪽 예제에서 짐작하신 분들도 있겠지만 array index 는 쉽게 말하면 '숫자같은 문자열' 입니다.
이 정의 역시 ECMAScript Spec에 나와 있는데요. CanonicalNumericIndexString(n)
의 결과가 +0
이상 2^32-2
이하인 경우라고 합니다. 이쪽도 파고 들어가면 자바스크립의 실제 문법 구조까지 나올 정도로 들어갈 수 있지만 저는 발만 담그고 얼른 빠져나왔습니다. CanonicalNumericIndexString(n)
은 주어진 문자열 n
을 ToString
하고 다시 ToNumber
한 결과가 정확히 n
과 일치하면 숫자를, 아니면 undefined
를 반환합니다. 이진법을 표현한 문자열이라면 ToNumber
의 결과가 십진법이니까 정확히 일치하지 않아요. 정말 십진법 숫자처럼 생긴 애들만 인정해줍니다.
주어진 문자열을 딱 봤을 때 십진수처럼 보인다면 array index라고 생각하는 게 편할 지도 모르겠네요.
예제
const test = {
qwer: null,
asdf: null,
0b10: null,
1: null,
'0b10': null,
};
console.log(Object.keys(test));
결과는 ['1', '2', 'qwer', 'asdf', '0b10']
입니다.
1
은 당연히 array index.
0b10
은 좀 복잡한데요. 객체로 주어진 key가 문자열 또는 심볼이 아니라면 객체 생성 시에 ToPropertyKey를 사용해서 변환 후에 넣는 것으로 보입니다. 그러면 애초에 들어갈 때부터 0b10
이 아니라 2
로 들어갔고, 이건 array index 가 맞죠.
나머지는 문자열이니 넣은 순서대로 갑니다.
참고) unordered set과 ordered set
결과적으로 자바스크립트 객체의 key 값들의 순서는 우리가 조종할 수 있는 부분이 아닙니다. Object.keys
는 나름의 정렬 방식은 있지만 그 결과를 저희가 원하는 대로 바꿀 수는 없으니까요. 그래서 객체는 unordered set입니다.
반대로 Set
이나 Map
은 값들을 순회할 때 무조건 넣은 순서대로 받을 수 있는데요. 이 친구들은 ordered set 이라고 부릅니다.
결론
Object.keys
의 결과물은 나름의 순서가 있지만 완벽한 시간 순은 아니다.
참고 자료
OrdinaryOwnPropertyKeys
array index
CanonicalNumericIndexString
ToNumber
ToString
ToPropertyKey
Object initializer runtime semantics
'자바스크립트' 카테고리의 다른 글
유사 배열(Indexed Collections, Array-like Objects) (0) | 2024.10.05 |
---|---|
자바스크립트로 우선순위 큐 만들기 (4) | 2023.11.17 |