[JS] #15 Map 오브젝트

simoniful·2021년 5월 1일
0

ES6 JS - Basic

목록 보기
15/18
post-thumbnail

형태

[Key, Value] pair collection

Map 오브젝트는 [key, value] 형태로 대괄호 내에 key와 value를 작성합니다. 다양한 타입을 Key로 사용할 수 있습니다.

const obj = new Map([
  ["key", "value"],
  [{book: 200}, "오브젝트"],
  [100, "Number"]
]);
for (let keyValue of obj) {
  console.log(keyValue);
};
// ["key", "value"]
// [{book:200}, "오브젝트"]
// [100, "Number"]

⇒ key의 타입으로 String, Object, Number, Symbol 이 사용됩니다 또한 Map의 key처리는 for-of문을 통해 작성한 순서대로 읽어서 처리할 수도 있습니다.


new Map()

Map 인스턴스를 생성하여 반환합니다. 파라미터에 이터러블 오브젝트를 작성합니다.

const obj = new Map([
  ["key", "value"],
  [100, "Number"]
]);
console.log(obj);
console.log(typeof obj);
// {}
// object

⇒ 파라미터를 배열 안에 배열로 작성합니다. 대괄호[]가 2개입니다.
⇒ 빈 Map을 만들 때는 파라미터를 작성하지 않아도 되며 이때는 new Map() 형태로 사용합니다.
⇒ new 연산자를 사용하지 않으면 typeError가 발생합니다.

Same-Value-Zero 비교 알고리즘

key값은 Same-Value-Zero 비교 알고리즘을 통해 식별하며, key값이 같으면 대체 합니다.

  • key 값을 비교

    const obj = new Map([
      [100, "Number"],
      ["100", "String"]
    ]);
    for (let [key, value] of obj) {
      console.log(`${key} : ${value}`);
    };
    // 100 : Number
    // 100 : String

    ⇒ 100과 "100"은 타입이 다릅니다.

  • key 값이 타입까지 같으면 value가 대체

    const obj = new Map([
      [100, "첫 번째"],
      [100, "두 번째"]
    ]);
    for (let [key, value] of obj) {
      console.log(`${key} : ${value}`);
    };
    // 100 : 두 번째
  • 잘못 작성한 형태

    try {
      new Map(["one", 1]);
    } catch {
      console.log("[[one, 1]]");
    };
    const obj = new Map([{five: 5}]);
    for (let [key, value] of obj) {
      console.log(`${key} : ${value}`);
    };
    // [[one, 1]]
    // undefined : undefined

    ⇒ key만 작성된 경우로 에러가 발생하지 않지만 key와 value에 undefined가 설정됩니다


Map과 Object 비교

Map 오브젝트 구조

  const map = Map;
  const list = [1, 2];
  const obj = new Map([
    ["one", "첫 번째"],
    ["two", "두 번째"]
  ]);

  1. Map 오브젝트에는 get Symbol(Symbol.species)가 있습니다. 따라서, constructor를 오버라이드 할 수 있습니다.
  2. prototype을 펼치면 Symbol.iterator가 있습니다. 즉, 이터레이터 오브젝트를 반환받아 반복할 수 있습니다.
  • Map과 배열의 구조

    • Map 인스턴스인 obj를 전개하면 [[Entries]]가 있습니다. 대괄호 두 개는 엔진에서 설정하는것을 의미합니다.
    • 이를 펼치면 0: {"key" ⇒ "value"} 형태로 나열되있는데 이는 배열구조와 유사합니다. Map 또한 인덱스를 부여하여 저장하기에 배열처럼 이터레이션이 가능합니다.
    • 배열과 맵 둘 다 요소 작성 순서대로 인덱스를 부여하여 해당 인덱스의 value로 입력값을 저장합니다. 따라서 작성된 순서대로 읽혀집니다.
    • list는 value만 있는 반면, map은 형태 {key ⇒ value}로 저장된다는 점이 차이점입니다.
    • size가 length의 기능을 합니다.

정리

  1. key
    • Map: 타입 제약 없음
    • Object: String, Symbol
  2. {key:value} 수
    • Map: size 프로퍼티로 구함
    • Object: 전체를 읽어서 구해야 함
  3. 처리 시간: MDN
    • key, value의 추가 삭제가 빈번할수록, Map이 더 뛰어난 성능을 보여줍니다.

값 설정, 추출 메소드

Map 오브젝트는 set, get, has 메소드를 사용해서 엔트리를 설정하거나 읽거나 할 수 있습니다.

set()

  • Map 인스턴스에 key, value 설정(다양한 타입)

    • key, value 순서로 파라미터 작성
    • key, value를 설정한 인스턴스 반환
      let obj = new Map();
      obj.set("one", 100);
      obj.set({}, "오브젝트");
      obj.set(function(){}, "Function");
      obj.set(new Number("100"), "인스턴스");
      obj.set(NaN, "Not a Number");
      for (let [key, value] of obj) {
        console.log(`${key} : ${value}`);
      };
      // one: 100
      // [object Object]: 오브젝트
      // function(){}: Function
      // 100: 인스턴스
      // NaN: Not a Number
  • key 값이 같으면 value가 바뀜

    let obj = new Map();
    const book = {};
    obj.set(book, "첫 번째");
    obj.set(book, "두 번째");
    for (let [key, value] of obj) {
      console.log(`${key} : ${value}`);
    };
    // [object Object]: 두 번째
    1. obj.set(book, "첫 번째");
      외부에 작성한 book 오브젝트의 메모리 주소를 key값으로 사용합니다.
    2. obj.set(book, "두 번째");
      book 오브젝트의 메모리 주소와 같은 key 값이 있으므로 값이 대체됩니다.

get()

  • Map에서 key 값이 같은 value 반환

    • key 값이 같지 않거나 타입이 다르면 undefined 반환

      let obj = new Map([
        ["one", 100],
        ["200", "String 타입"]
      ]);
      console.log(obj.get("one"));
      console.log(obj.get("two"));
      console.log(obj.get(200));
      // 100
      // undefined
      // undefined

      ⇒ two 값이 key에 없고, 200은 타입이 다르므로 undefined 반환

    • 오브젝트 추출

      let obj = new Map();
      const like = {sports: "스포츠"};
      obj.set(like, {value: "농구"});
      console.log(obj.get(like));
      // {value: 농구}

      ⇒ set과 get에 작성한 like는 같은 메모리 주소를 사용합니다.

has()

  • Map 인스턴스에서 key의 존재 여부를 반환
    • key가 있으면 true, 아니면 false
      const obj = new Map([
        ["one", 100]
      ]);
      console.log(obj.has("one"));
      console.log(obj.has("two"));
      // true
      // false

Map과 이터레이터 오브젝트

entries()

  • Map 인스턴스로 이터레이터 오브젝트 생성, 반환
    • Map 인스턴스에 설정된 순서로 반환
    • next()로 [key, value] 반환
      const obj = new Map([
        ["one", 100],
        ["two", 200]
      ]);
      const iter = obj.entries();
      console.log(iter.next());
      console.log(iter.next());
      console.log(iter.next());
      // {value: [one, 100], done: false}
      // {value: [two, 200], done: false}
      // {value: undefined, done: true}

keys()

  • Map 인스턴스의 key로 이터레이터 오브젝트 생성, 반환
    • value는 포함하지 않음
    • Map 인스턴스에 설정된 순서로 반환
  • next()로 key 반환
    const obj = new Map([
      ["one", 100],
      ["two", 200]
    ]);
    const iter = obj.keys();
    console.log(iter.next());
    console.log(iter.next());
    console.log(iter.next());
    // {value: one, done: false}
    // {value: two, done: false}
    // {value: undefined, done: true}

values()

  • Map 인스턴스의 value로 이터레이터 오브젝트 생성, 반환
    • key는 포함하지 않음
    • Map 인스턴스에 설정된 순서로 반환
  • next()로 value 반환
    const obj = new Map([
      ["one", 100],
      ["two", 200]
    ]);
    const iter = obj.values();
    console.log(iter.next());
    console.log(iter.next());
    console.log(iter.next());
    // {value: 100, done: false}
    // {value: 200, done: false}
    // {value: undefined, done: true}

Symbol.iterator()

  • Map 인스턴스로 이터레이터 오브젝트 생성, 반환
    • Map.prototype.entries()와 같음
    • next()로 [key, value] 반환
      const obj = new Map([
        ["one", 100],
        ["two", 200]
      ]);
      const iter = obj[Symbol.iterator]();
      console.log(iter.next());
      console.log(iter.next());
      console.log(iter.next());
      // {value: [one, 100], done: false}
      // {value: [two, 200], done: false}
      // {value: undefined, done: true}

콜백함수를 가진 메소드, 삭제, 지우기

forEach()

  • Map 인스턴스를 반복하면서 콜백 함수를 호출합니다.

    • map(), filter() 등의 콜백 함수가 동반되는 메소드는 사용이 불가능합니다.
  • 콜백 함수에 넘겨주는 파라미터

    • value, key, Map 인스턴스 - key, value순서가 아님

      const obj = new Map([
        ["one", 100],
        ["two", 200]
      ]);
      const callback = (value, key, map) => {
        console.log(`${key}, ${value}`);
      };
      obj.forEach(callback);
      // one, 100
      // two, 200
    • 콜백 함수에서 this사용

      const obj = new Map([
        ["one", 100],
        ["two", 200]
      ]);
      function callback(value, key, map){
        console.log(`${key}, ${value}, ${this.check}`);
      };
      obj.forEach(callback, {check: 50});
      // one, 100, 50
      // two, 200, 50

      ⇒ 콜백 함수를 일반 함수로 작성, 화살표 함수로 작성 시 this가 window 오브젝트 참조합니다.
      ⇒ this가 forEach()의 두 번째 파라미터에 작성한 오브젝트를 참조합니다.

delete()

  • Map 인스턴스에서 파라미터 값과 같은 entry 삭제
    • 같은 key가 있으면(삭제 성공) true 반환, 없으면(삭제 실패) false 반환
      const obj = new Map([
        ["one", 100],
        [{}, "오브젝트"]
      ]);
      console.log(obj.delete("one"));
      console.log(obj.delete({}));
      const sports = {};
      obj.set(sports, "스포츠");
      console.log(obj.delete(sports));
      // true
      // false  --- 
      // true
      ⇒ 참조하는 메모리 주소가 달라서 {}의 경우는 삭제 실패
      ⇒ sports로 할당시에는 set과 delete의 sports는 같은 메모리를 나타내므로 삭제 성공

clear()

  • Map인스턴스의 모든 entry를 지웁니다.
    • Map인스턴스 자체를 삭제하는것은 아니며 내부의 entry만 지웁니다.
    • 따라서 다시 [key, value]를 추가할 수 있습니다.
  • size 프로퍼티
    • Map 인스턴스의 entry 수를 반환, Array 오브젝트의 length와 유사
    • 개발자 코드로 수정할 수 없음 (length는 수정 가능)
      const obj = new Map([
        ["one", 100],
        ["two", 200]
      ]);
      console.log(obj.size);
      obj.clear();
      console.log(obj.size);
      obj.set("add", "추가");
      console.log(obj.size);
      // 2
      // 0
      // 1
profile
소신있게 정진합니다.

0개의 댓글