객체의 순서를 보장하기

 const obj = { "12": "c", "123": "a", "1": "b" };
 
 console.log(Object.values(obj)); // c a b 가 아닌 b c a

왜 배열는 순서보장이 되고 객체는 순서보장이 되지 않을까?

배열은 인덱스 기반 자료구조라 순서보장이된다.

const arr = ["a", "b", "c"];

{
  0: "a",
  1: "b", 
  2: "c",
  length: 3,
  __proto__: Array.prototype
}

반면, 객체는 접근 자체가 중요한 자료구조라 순서를 따지지않도록 설계되었다. (해시 테이블)

{
  "id"    → hash("id")    → 메모리 주소 0xABC
  "name"  → hash("name")  → 메모리 주소 0x123  
  "email" → hash("email") → 메모리 주소 0x789
}

해시 함수가 주소를 결정한다.

키가 곧 주소가 되므로, 순서가 보장되지 않는 대신 O(1) 으로 접근이 가능하다.

그럼 어떻게 객체의 순서를 보장할 수 있을까?

정답은 Map 을 사용하면 된다.

Map 은 해시 테이블 + 연결 리스트로 구성된다.

hashTable: {
  "name" → Node1의 주소
  "age"  → Node2의 주소  
  "city" → Node3의 주소
}

head ↔ Node1 ↔ Node2 ↔ Node3 ↔ tail
       (name)  (age)   (city)

여전히 노드 주소를 가지므로 곧 바로 접근이 가능하다.

순서를 위한 추가 노드 속성이 필요하므로 추가 메모리가 필요하게 된다.

{
  key: "name",
  value: "Kim"
}

{
  key: "name",
  value: "Kim",
  prev: 이전 노드 주소,  // +8 bytes
  next: 이후 노드 주소   // +8 bytes
}

연결 리스트 특성으로 순서를 보장하면서도 더 빠른 순회를 제공한다.