ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [ES6] WeakMap vs Map [번역]
    맨땅에코딩/javascript 2020. 8. 9. 23:32

     [서문]

     

    Garbage Collection : JavaScript 엔진은 value를 메리에 저장하는데 ( 잠재적으로 사용될 수 있을동안 )

     

    let john = { name: "John" };
    
    // the object can be accessed, john is the reference to it
    
    // overwrite the reference
    john = null;

    보통, 객체의 프로퍼티 혹은 배열이나 다른 데이터 구조의 요소들은 메모리에 그 데이터구조가 있을 동안만 접근 가능하다.

     

    예를 들어, 배열에 객체를 넣을때, 그리고 배열은 살아있을때, 그 객체에 다른 참조가 없을때도 배열안에 있는 객체는 살아있다.

     

    let john = { name: "John" };
    
    let array = [ john ];
    
    john = null; // overwrite the reference
    // john is stored inside the array, so it won't be garbage-collected
    // we can get it as array[0]

     

    Map또한 마찬가지인데,  Map이 존재하는 동안 Map에 담긴 object도 존재한다.

    메모리를 차지하고 gc 되지 않을 것이다.

     

    let john = { name: "John" };
    
    let map = new Map();
    map.set(john, "...");
    
    john = null; // overwrite the reference
    
    // john is stored inside the map,
    // we can get it by using map.keys()

     

    WeakMap은 근본적으로 이러한 관점에서 다르다.

    key object의 gc를 보호하지 않는다.

     

    [차이점]

     

    1. WeakMap 의 key는 반드시 object여야 한다. ( integer , string X )

    2. WeakMap의 key인 object의 참조부분이 없다면 - 메모리로부터 자동적으로 지워질것이다.

     

    let john = { name: "John" };
    
    let weakMap = new WeakMap();
    weakMap.set(john, "...");
    
    john = null; // overwrite the reference
    
    // john is removed from memory!

     

    3. WeakMap은 iteration 과 keys(), values(), entries() 메소드를 지원하지 않는다.

     

    * 지원가능한 메소드

    • weakMAp.get(key)
    • weakMap.set(key, value)
    • weakMap.delete(key)
    • weakMap.has(key)

    왜 이러한 제한이 있을까?

    : 기술적인 이유때문이다. 만약 object 모든 참조를 잃었다면 (위에 John 처럼) , 자동적으로 gc 처리된다.

    하지만 기술적으로 삭제되는 상황을 설명한건 아니다.

     

    JavaScript 엔진은 메모리 비움을 즉시 수행할 수도 있고 다른 삭제상황이 있을때를 기다릴 수도 있다.

    따라서, 기술적으로 WeakMap의 현재의 요소는 알 수 없는 상태이다.

    지워졌을 수도 안지워졌을 수도 있어서.. 혹은 부분적으로 

    그러한 이우로 key/value에 접근하는 메소드는 지원되지않는다.

     

      [언제 WeakMap을 사용해?]

     

    1. 추가적 데이터 

     WeakMap의 어플리케이션의 주요 사용처는 "추가적인 데이터 저장소" 이다.

     

    만약 우리가 다른 코드에 속한 object를 작업하고 있다면 (아마도 thrid-party 라이브러리에서)

    그 것으로 데이터를 저장하길 원하며, 오직 그 object가 살아있을때만 존재해야 할때

    WeakMap 은 딱맞는 예제이다.

     

    예제를 살펴보자.

     

    사용자별 방문자수를 보유하는 코드를 작성한다고 가정하자.

    Map안에 저장된 정보는 이러하다 : 사용자 object는 key이고 방문자수는 value다.

    사용자가 떠나면 ( garbage collected ) 우리는 그 사용자의 방문수를 더이상 저장하고싶지않다.

     

    Map 이용

    // 📁 visitsCount.js
    let visitsCountMap = new Map(); // map: user => visits count
    
    // increase the visits count
    function countUser(user) {
      let count = visitsCountMap.get(user) || 0;
      visitsCountMap.set(user, count + 1);
    }
    
    // 📁 main.js
    let john = { name: "John" };
    
    countUser(john); // count his visits
    
    // later john leaves us
    john = null;

     : John object는 gc 처리돼야 하는데 visitsCountMap의 key로 남아있다.

     

    그렇다면, 우리는 사용자가 탈퇴할때, visitsCountMap을 비워야한다. 그렇지않으면, 메모리에 무기한으로 남아있을 것이다. 이러한 비움작업은 귀찮은 작업이 될 수 있다.

     

     

    WeakMap 이용

    // 📁 visitsCount.js
    let visitsCountMap = new WeakMap(); // weakmap: user => visits count
    
    // increase the visits count
    function countUser(user) {
      let count = visitsCountMap.get(user) || 0;
      visitsCountMap.set(user, count + 1);
    }

    : 우리는 visitsCountMap을 비울 필요가 없다. John object가 WeakMap의 key를 제외하고 접근 불가능해졌을때,

    메모리로부터 제거된다. 

     

    2. Caching

    :  함수의 결과가 기억돼야할때, 같은 object를 재사용하여 호출한다.

     

    Map 이용

     

    // 📁 cache.js
    let cache = new Map();
    
    // calculate and remember the result
    function process(obj) {
      if (!cache.has(obj)) {
        let result = /* calculations of the result for */ obj;
    
        cache.set(obj, result);
      }
    
      return cache.get(obj);
    }
    
    // Now we use process() in another file:
    
    // 📁 main.js
    let obj = {/* let's say we have an object */};
    
    let result1 = process(obj); // calculated
    
    // ...later, from another place of the code...
    let result2 = process(obj); // remembered result taken from cache
    
    // ...later, when the object is not needed any more:
    obj = null;
    
    alert(cache.size); // 1 (Ouch! The object is still in cache, taking memory!)

    : 같은 object로 여러번의 process(obj) 를 할때, 처음에만 결과를 계산한다. 그 후에는 cache에서 값을 가져온다.

     문제는, 그 object가 더이상 필요하지않을때 우리는 cache를 비울 필요가 있다.

     

     

     WeakMap 이용

     

    // 📁 cache.js
    let cache = new WeakMap();
    
    // calculate and remember the result
    function process(obj) {
      if (!cache.has(obj)) {
        let result = /* calculate the result for */ obj;
    
        cache.set(obj, result);
      }
    
      return cache.get(obj);
    }
    
    // 📁 main.js
    let obj = {/* some object */};
    
    let result1 = process(obj);
    let result2 = process(obj);
    
    // ...later, when the object is not needed any more:
    obj = null;
    
    // Can't get cache.size, as it's a WeakMap,
    // but it's 0 or soon be 0
    // When obj gets garbage collected, cached da

    : WeakMap은 object가 gc로 수집된 후에 자동으로 메모리에서 지워준다.

     

    let messages = [
      {text: "Hello", from: "John"},
      {text: "How goes?", from: "John"},
      {text: "See you soon", from: "Alice"}
    ];
    
    let readMap = new WeakMap();
    
    readMap.set(messages[0], new Date(2017, 1, 1));
    // Date object we'll study later

    : Set은 object의 yes/no 여부만 알 수 있지만 Map은 값을 저장할 수 있다. 

     

     

     

    [원문]

    https://javascript.info/weakmap-weakset

     

    '맨땅에코딩 > javascript' 카테고리의 다른 글

    apply,call,bind 비교  (0) 2020.09.11
    [ES6] WeakSet vs Set [번역]  (0) 2020.08.09
    [ES6] Set vs Array 비교 [번역]  (0) 2020.08.07
    [ES6] Map vs Object 비교 [번역]  (0) 2020.08.07
    [ES6] var, let, const 비교  (0) 2020.06.26
Designed by Tistory.