JS 공식문서 스터디 7. Key 기반 컬렉션 ~ 객체로 작업하기

CHO WanGi·2025년 9월 9일

Javascript

목록 보기
17/20

Map & Set

Map 객체

ES6에서 등장한 값을 Mapping 하기 위한 새로운 데이터 구조
set, get, has, delete 등의 메서드 활용 가능

var sayings = new Map();
sayings.set("dog", "woof");
sayings.set("cat", "meow");
sayings.set("elephant", "toot");
sayings.size; // 3
sayings.get("fox"); // undefined
sayings.has("bird"); // false
sayings.delete("dog");

for (var [key, value] of sayings) {
  console.log(key + " goes " + value);
}
// "cat goes meow"
// "elephant goes toot"

for of를 통해 반복도 가능하다.

object vs Map

// Object
const obj = {};
obj["name"] = "Wangi";
obj[123] = "숫자도 넣긴 되지만 자동으로 문자열 '123'이 됨";
obj[{ x: 1 }] = "객체 키? -> '[object Object]' 로 변환됨";

console.log(obj["name"]);      // Wangi
console.log(obj[123]);         // 숫자도 사실은 문자열 "123" 키
console.log(obj);              // { '123': '숫자도...', name: 'Wangi', '[object Object]': '객체 키?...' }

// Map
const map = new Map();
map.set("name", "Wangi");
map.set(123, "숫자 키 그대로 저장됨");
map.set({ x: 1 }, "객체도 고유 키로 저장됨");

cons
  • object
    전통적으로, 문자열을 값에 매핑하는데 사용, Key를 주로 활용

  • Map
    object의 키는 문자열이지만, Map의 Key는 모든 값을 가질 수 있다.
    또한 Map은 크기를 쉽게 얻는 것이 가능.

Mdn Guide

  • 실행시까지 키를 알 수 없고, 모든 키가 동일한 타입이라면 Map을 사용
  • 각 개별 요소에 대해 적용 가능한 로직이 있는 경우 objects 사용

weakmap

map과 비슷하지만 메모리 관리를 위해 특별하게 설계된 구조
객체만 키로 가능

  • 키가 약하게 참조 => GC 대상이 되면 자동 제거
  • 순회 볼가능 => 위의 이유로, 언제 GC 될지 모르기 때문
 let obj = { name: "Wangi" };

// Map은 문자열도 키로 가능
const map = new Map();
map.set("name", "값");
console.log(map.get("name")); // "값"

// WeakMap은 객체만 키 가능
const wm = new WeakMap();
wm.set(obj, "개인 정보");

console.log(wm.get(obj)); // "개인 정보"
console.log(wm.has(obj)); // true

// obj 참조를 끊으면?
obj = null;
// 여기서 가비지 컬렉션이 돌면 WeakMap 안의 키-값도 자동 제거됨

Set

값들의 집합, 중복 허용 X

배열과 Set의 상호 변환 : 전개 연산자(...)

Array.from(mySet);
[...mySet2];

mySet2 = new Set([1, 2, 3, 4]);

weakSet

weakMap의 Set 버전이다.

Set의 Value, Map의 Key 값 비교 : SameValueZero

일치 연산자 === 와 거의 동일하게 작동하나, 0 비교에서 좀 다르다

console.log(-0 === +0); // true
  • MAP에서의 key 비교
const map = new Map();
map.set(+0, "plus zero");
map.set(-0, "minus zero");
map.set(NaN, "not a number");

console.log(map.size);      // 2
console.log(map.get(0));    // "minus zero" (사실상 같은 key 취급)
console.log(map.get(NaN));  // "not a number"
  • Set에서의 value 비교
const set = new Set();
set.add(+0);
set.add(-0);
set.add(NaN);
set.add(NaN);

console.log(set.size);  // 2
console.log(set.has(0)); // true

객체로 작업하기

JS는 간단한 객체 기반 패러다임,

객체의 개요

JS에서의 객체 => 속성과 타입을 가진 독립적 개채(entity)
현실의 사물과 비슷한 개념

  • 객체의 생성
  1. 리터럴
const myCar = {
  make: "Ford",
  model: "Mustang",
  year: 1969
};
  1. new + 생성자 함수
function Car(make, model, year) {
  this.make = make;
  this.model = model;
  this.year = year;
}
const myCar = new Car("Eagle", "Talon TSi", 1993);

인스턴스 여러개를 생성할 때 유용하다

  • 객체의 속성 접근
  1. 점 표기법 : object.property
  2. 대괄호 표기법 : object["property"]

상속

JS는 prototype 기반 언어.
프로토타입은 객체의 부모역할을 하는 또다른 객체를 말함.

Prototype

  • JS에는 원래는 Class가 없었음(ES6에서 새로 등장)
function Person() {
  this.eyes = 2;
  this.nose = 1;
}

var kim  = new Person();
var park = new Person();

console.log(kim.eyes);  // => 2
console.log(kim.nose);  // => 1
console.log(park.eyes); // => 2
console.log(park.nose); // => 1

kim, park 은 서로 eyes와 nose 공통적으로 가짐.
메모리에는 eye와 nose가 총 4개 할당.
이렇게 되면 만약, 객체를 100개 만들면 그만큼 메모리에 변수 할당되는 문제가 발생

  • Prototype 적용
function Person() {}

Person.prototype.eyes = 2;
Person.prototype.nose = 1;

var kim  = new Person();
var park = new Person():

console.log(kim.eyes);  // => 2
console.log(kim.nose);  // => 1
console.log(park.eyes); // => 2
console.log(park.nose); // => 1

프로토 타입 체인

모든 객체는 내부적으로 [[Prototype]], 보통 __proto__ 로 접근
어떤 속성을 객체 에서 못찾으면, JS는 그 객체의 프로토타입에서 찾음

const animal = {
  eats: true
};

const dog = Object.create(animal); // animal을 prototype으로 하는 새로운 객체
dog.barks = true;

console.log(dog.eats);  // true (animal에서 상속받음)
console.log(dog.barks); // true (자기 자신의 속성)

dog에 eats라는 속성은 없으나, 프로토타입인 animal에 있기에 true
이렇게 위로 올라가는 과정을 프로토타입 체인이라 함.

  • Prototype Chain 의 끝
    null을 가진 객체에 도달시까지 계속 타고 올라감.
    여기서 머리가 아픈데, 프로토타입의 체인의 모든 구성 요소들을 변경 혹은
    런타임시 프로토타입 교체 가능 => 정적 dispatching 의 개념이 없다.

생성자 함수와 프로토타입

function Person(name) {
  this.name = name;
}

Person.prototype.greet = function() {
  console.log(`Hi, I'm ${this.name}`);
};

const alice = new Person("Alice");
alice.greet(); // Hi, I'm Alice

alice 객체에는 greet이 직접 정의는 안되어있으나 Person.prototype에 있어서 사용 가능

클래스 문법

ES6+ 에서 추가, 더 익숙하게 표현 가능
여전히 내부적으로는 프로토타입 체인 사용

class Animal {
  constructor(name) {
    this.name = name;
  }
  eat() {
    console.log(`${this.name} is eating`);
  }
}

class Dog extends Animal {
  bark() {
    console.log(`${this.name} is barking`);
  }
}

const myDog = new Dog("Buddy");
myDog.eat();  // Buddy is eating (Animal에서 상속받음)
myDog.bark(); // Buddy is barking (Dog 고유 메서드)
profile
제 Velog에 오신 모든 분들이 작더라도 인사이트를 얻어가셨으면 좋겠습니다 :)

0개의 댓글