
요약
좀 다름
들어가는 말
자바스크립트는 온 세상이 객체라고 해도 될 정도이긴 하지만, 객체의 활용법 중 하나는 마치 파이썬의 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 |