es6 지도 와 Weak 지도

12811 단어
Map
JavaScript 의 대상 (Object) 은 본질 적 으로 키 값 이 맞 는 집합 (Hash 구조) 이지 만 전통 적 으로 문자열 을 키 로 만 사용 할 수 있 습 니 다.이것 은 그것 의 사용 에 매우 큰 제한 을 가 져 왔 다.이 문 제 를 해결 하기 위해 ES6 는 Map 데이터 구 조 를 제공 했다.이것 은 대상 과 유사 하고 키 값 이 맞 는 집합 이지 만 '키' 의 범 위 는 문자열 에 국한 되 지 않 으 며 각종 유형의 값 (대상 포함) 을 키 로 사용 할 수 있다.즉, Object 구 조 는 '문자열 - 값' 의 대응 을 제 공 했 고 Map 구 조 는 '값 - 값' 의 대응 을 제 공 했 으 며 더욱 완벽 한 Hash 구조 구현 이다."키 쌍" 의 데이터 구조 가 필요 하 다 면, 맵 은 Object 보다 더 적합 합 니 다.
지도의 구조
ES6 의 Map 유형 은 키 가 맞 는 서열 표 이 고 키 와 값 은 임의의 유형 일 수 있 습 니 다.키 의 비 교 는 Object. is () 를 사용 하기 때문에 5 와 "5" 를 사용 할 수 있 습 니 다.
유형 이 다 르 기 때문에 키 로 동시에 사용 합 니 다.이것 은 대상 속성 을 키 로 사용 하 는 방식 (대상 으로 맵 을 모 의 하 는 것 을 가리 키 는 말) 과 는 달리 대상 의 속성 이 문자열 로 강제로 변환 되 기 때문이다.
set 방법 구조
set () 방법 을 호출 하여 키 와 연 결 된 값 을 전달 하여 맵 에 항목 을 추가 할 수 있 습 니 다.이후 get () 방법 을 키 이름 으로 호출 하면 해당 하 는 값 을 추출 할 수 있 습 니 다.예 를 들 면:
let map = new Map();
map.set("title", "Understanding ES6");
map.set("year", 2016);
console.log(map.get("title")); // "Understanding ES6"
console.log(map.get("year")); // 2016

배열 구조
여전히 set 와 유사 합 니 다. 맵 구조 기 에 배열 을 전달 하여 데 이 터 를 사용 하여 맵 을 초기 화 할 수 있 습 니 다.이 배열 의 모든 항목 도 배열 이 어야 하고 내부 배열 의 첫 번 째 항목 은 키 가 되 며 두 번 째 항목 은 대응 값 이다.그래서 전체 맵 은 이 두 개의 배열 로 채 워 졌 다.예 를 들 면:
let map = new Map([["name", "Nicholas"], ["age", 25]]);
console.log(map.has("name")); // true
console.log(map.get("name")); // "Nicholas"
console.log(map.size); // 2

구조 기 에서 초기 화 를 통 해 "name" 과 "age" 두 키 는 map 변수 에 추 가 됩 니 다.배열 로 구 성 된 배열 이 이상 하 게 보이 지만 정확 한 표현 키 는 필요 하 다. 키 는 임의의 데이터 형식 을 허용 하기 때문에 키 를 배열 에 저장 하 는 것 은 맵 에 추가 되 기 전에 다른 유형 으로 강제 전환 되 지 않도록 하 는 유일한 방법 이다.Map 구조 함 수 는 배열 을 매개 변수 로 받 아들 이 고 실제 적 으로 다음 알고리즘 을 실행 합 니 다.
const items = [
["name", "Nicholas"]
  ["age", 25] ]
  
  const map = new Map();
  
  items.forEach(
    ([key, value]) => map.set(key, value)
  );

사실은 배열 뿐만 아니 라 Iterator 인 터 페 이 스 를 가 진 모든 구성원 이 하나의 이중 요소 인 배열 의 데이터 구 조 는 Map 구조 함수 의 매개 변수 로 사용 할 수 있다.셋 과 맵 모두 새로운 맵 을 만 드 는 데 쓸 수 있다 는 얘 기다.
기타 구조
 const set = new Set([
      ['foo', 1],
      ['bar', 2]
    ]);
const m1 = new Map(set);
m1.get('foo') // 1

const m2 = new Map([['baz', 3]]);
const m3 = new Map(m2);
m3.get('baz') // 3

위의 코드 에서 우 리 는 각각 set 대상 과 Map 대상 을 사용 하여 Map 구조 함수 의 매개 변수 로 삼 았 고 결 과 는 모두 새로운 Map 대상 을 생 성 했다.
맵 의 속성 과 방법
1. 속성
Map 역시 size 속성 을 가지 고 있 습 니 다. 키 값 이 몇 개 포함 되 어 있 는 지 가리 키 는 데 사 용 됩 니 다.
2. 방법
2.1 조작 방법
2.11、set(key, value)
set 방법 은 키 이름 key 에 대응 하 는 키 값 을 value 로 설정 하고 전체 맵 구 조 를 되 돌려 줍 니 다.키 가 값 이 있 으 면 키 값 이 업 데 이 트 됩 니 다. 그렇지 않 으 면 이 키 를 새로 생 성 합 니 다.
const m = new Map();
m.set('edition', 6)        //      
m.set(262, 'standard')     //     
m.set(undefined, 'nah')    //    undefined

set 방법 은 현재 맵 대상 을 되 돌려 주기 때문에 체인 으로 쓸 수 있 습 니 다.
let map = new Map()
  .set(1, 'a')
  .set(2, 'b')
  .set(3, 'c');

2.12、get(key)
get 방법 은 key 에 대응 하 는 키 값 을 읽 습 니 다. key 를 찾 지 못 하면 undefined 로 돌아 갑 니 다.
const m = new Map();
const hello = function() {console.log('hello');};
m.set(hello, 'Hello ES6!') //     

m.get(hello)  // Hello ES6!

2.13、has、delete、clear
Map 과 Set 는 몇 가지 방법 을 공 유 했 습 니 다. 이것 은 의도 적 인 것 입 니 다. 비슷 한 방식 으로 Map 과 Set 와 상호작용 을 할 수 있 도록 합 니 다.다음 세 가지 방법 은 맵 과 set 에서
위 에 모두 존재 합 니 다:
2.13.1、has(key)
has 방법 은 현재 맵 대상 에 키 가 있 는 지 여 부 를 나타 내 는 불 값 을 되 돌려 줍 니 다.
const m = new Map();
m.set('edition', 6);
m.set(262, 'standard');
m.set(undefined, 'nah');
m.has('edition')     // true
m.has('years')       // false
m.has(262)           // true
m.has(undefined)     // true

2.13.2、delete(key)
delete 방법 은 키 를 삭제 하고 트 루 로 돌아 갑 니 다.삭제 에 실패 하면 false 로 돌아 갑 니 다.
const m = new Map();
m.set(undefined, 'nah');
m.has(undefined)     // true

m.delete(undefined)
m.has(undefined)       // false

2.13.4、clear()
clear 방법 은 모든 구성원 을 삭제 하고 값 을 되 돌려 주지 않 습 니 다.
let map = new Map();
map.set('foo', true);
map.set('bar', false);

map.size // 2
map.clear()
map.size // 0

2.2 옮 겨 다 니 는 방법
2.2.1 달력 생 성 함수
• keys (): 키 이름 의 스 트 리밍 기 를 되 돌려 줍 니 다.values (): 키 값 을 되 돌려 주 는 달력 입 니 다.entries (): 모든 구성원 의 달력 을 되 돌려 줍 니 다.
특히 주의해 야 할 것 은 맵 의 옮 겨 다 니 는 순 서 는 삽입 순서 다.
const map = new Map([
  ['F', 'no'],
  ['T',  'yes'],
]);

for (let key of map.keys()) {
  console.log(key);
}
// "F"
// "T"

for (let value of map.values()) {
  console.log(value);
}
// "no"
// "yes"

for (let item of map.entries()) {
  console.log(item[0], item[1]);
}
// "F" "no"
// "T" "yes"

//   
for (let [key, value] of map.entries()) {
  console.log(key, value);
}
// "F" "no"
// "T" "yes"

//      map.entries()
for (let [key, value] of map) {
  console.log(key, value);
}
// "F" "no"
// "T" "yes"

위 코드 의 마지막 예 는 맵 구조의 기본 스 트 리밍 인터페이스 (Symbol. iterator 속성) 를 나타 내 는 것 이 바로 entries 방법 입 니 다.
2.2.2、forEach
Map 의 foreach () 방법 은 set 와 배열 의 동명 방법 과 유사 합 니 다. 세 개의 매개 변 수 를 받 을 수 있 는 반전 함 수 를 받 습 니 다.
  • 맵 의 다음 위치 값;
  • 이 값 에 대응 하 는 키;
  • 목표 맵 자체.

  • 리 셋 함수 의 이러한 매개 변 수 는 배열 foreach () 방법의 행위 에 더욱 밀접 하 게 부합된다. 즉, 첫 번 째 매개 변 수 는 값 이 고 두 번 째 매개 변 수 는 키 (배열 의 키 는 수치 색인) 이다.여기 예제 가 있 습 니 다:
    let map = new Map([
      ["name", "Nicholas"], 
      ["age", 25]
    ]);
    map.forEach(function(value, key, ownerMap) {
      console.log(key + " " + value);
      console.log(ownerMap === map);
    });
    

    foreach () 의 반전 함수 가 전 달 된 정 보 를 출력 합 니 다.그 중에서 value 와 key 가 직접 출력 되 었 고 ownermap 와 map 를 비교 한 것 은 똑 같다 는 것 을 의미한다.출력 합 니 다:
    name Nicholas
    true
    age 25
    true    
    

    맵 과 기타 데이터 구조의 상호 교환
    맵 전환 배열:
    Map 구 조 를 배열 구조 로 바 꾸 고 빠 른 방법 은 확장 연산 자 (...) 를 사용 하 는 것 입 니 다.
    const map = new Map([
      [1, 'one'],
      [2, 'two'],
      [3, 'three'],
    ]);
    [...map.keys()]
    // [1, 2, 3]
    [...map.values()]
    // ['one', 'two', 'three']
    [...map.entries()]
    // [[1,'one'], [2, 'two'], [3, 'three']]
    [...map]
    // [[1,'one'], [2, 'two'], [3, 'three']]
    

    배열 이 맵 으로 바 뀌 었 습 니 다.
    맵 구조 함수 에 배열 을 전송 하면 맵 으로 전환 할 수 있 습 니 다.
    new Map([
      [true, 7],
      [{foo: 3}, ['abc']]
    ])
    // Map {
    //   true => 7,
    //   Object {foo: 3} => ['abc']
    // }
    

    맵 대상
    모든 맵 의 키 가 문자열 이 라면 대상 으로 손상 없 이 전환 할 수 있 습 니 다.
    function strMapToObj(strMap) {
      let obj = Object.create(null);
      for (let [k,v] of strMap) {
        obj[k] = v;
      }
      return obj;
    }
    
    const myMap = new Map()
      .set('yes', true)
      .set('no', false);
    strMapToObj(myMap)
    // { yes: true, no: false }
    

    문자열 이 아 닌 키 이름 이 있 으 면 이 키 이름 은 문자열 로 바 뀌 어 대상 의 키 이름 으로 바 뀝 니 다.
    대상 이 맵 으로 전환
    function objToStrMap(obj) {
      let strMap = new Map();
      for (let k of Object.keys(obj)) {
        strMap.set(k, obj[k]);
      }
      return strMap;
    }
    
    objToStrMap({yes: true, no: false})
    // Map {"yes" => true, "no" => false}
    

    맵 이 JSON 으로 바 뀌 었 습 니 다.
    맵 을 JSON 으로 전환 하려 면 두 가지 상황 을 구분 해 야 한다.맵 의 키 이름 이 모두 문자열 인 경우 대상 JSON 으로 전환 하 는 것 을 선택 할 수 있 습 니 다.
    function strMapToJson(strMap) {
      return JSON.stringify(strMapToObj(strMap));
    }
    
    let myMap = new Map().set('yes', true).set('no', false);
    strMapToJson(myMap)
    // '{"yes":true,"no":false}'
    

    또 다른 경 우 는 맵 의 키 이름 에 비 문자열 이 있 습 니 다. 이 때 배열 JSON 으로 전환 하 는 것 을 선택 할 수 있 습 니 다.
    function mapToArrayJson(map) {
      return JSON.stringify([...map]);
    }
    
    let myMap = new Map().set(true, 7).set({foo: 3}, ['abc']);
    mapToArrayJson(myMap)
    // '[[true,7],[{"foo":3},["abc"]]]'
    

    JSON 지도 로 전환
    JSON 이 Map 으로 바 뀌 면 모든 키 이름 이 문자열 입 니 다.
    function jsonToStrMap(jsonStr) {
      return objToStrMap(JSON.parse(jsonStr));
    }
    
    jsonToStrMap('{"yes": true, "no": false}')
    // Map {'yes' => true, 'no' => false}
    

    그러나 JSON 전체 가 하나의 배열 이 고 각 배열 의 구성원 자체 가 두 명의 구성원 이 있 는 배열 이라는 특수 한 상황 이 있다.이 때 는 일일이 대응 해 맵 으로 전환 할 수 있다.이 는 종종 맵 이 배열 JSON 으로 바 뀌 는 역작 동 이다.
      function jsonToMap(jsonStr) {
          return new Map(JSON.parse(jsonStr));
        }
    
    jsonToMap('[[true,7],[{"foo":3},["abc"]]]')
    // Map {true => 7, Object {foo: 3} => ['abc']}
    

    WeakMap:
    WeakMap 의 특성
    Weak Map 과 Map 의 차 이 는 두 가지 가 있 습 니 다.우선, WeakMap 은 대상 만 키 이름 (null 제외) 으로 받 아들 이 고, 다른 종류의 값 은 키 이름 으로 받 아들 이지 않 습 니 다.
    const map = new WeakMap();
    map.set(1, 2)
    // TypeError: 1 is not an object!
    map.set(Symbol(), 2)
    // TypeError: Invalid value used as weak map key
    map.set(null, 2)
    // TypeError: Invalid value used as weak map key
    

    그 다음으로 WeakMap 의 키 이름 이 가리 키 는 대상 은 쓰레기 회수 메커니즘 에 포함 되 지 않 습 니 다.WeakMap 의 디자인 목적 은 때때로 우 리 는 특정한 대상 에 데 이 터 를 저장 하고 싶 지만 이 대상 에 대한 인용 이 형성 된다 는 것 이다.아래 의 예 를 보십시오.
    const e1 = document.getElementById('foo');
    const e2 = document.getElementById('bar');
    const arr = [
      [e1, 'foo   '],
      [e2, 'bar   '],
    ];
    

    위의 코드 에서 e1 과 e2 는 두 개의 대상 입 니 다. 우 리 는 arr 배열 을 통 해 이 두 대상 에 대해 문자 설명 을 추가 합 니 다.이것 은 arr 가 e1 과 e2 에 대한 인용 을 형성 했다.이 두 대상 이 더 이상 필요 하지 않 으 면 이 인용 을 수 동 으로 삭제 해 야 합 니 다. 그렇지 않 으 면 쓰레기 회수 체 제 는 e1 과 e2 가 사용 하 는 메모 리 를 방출 하지 않 습 니 다. /e1 과 e2 가 필요 없 을 때 / / 인용 을 수 동 으로 삭제 해 야 합 니 다.
    arr [0] = null;
    arr [1] = null;
    

    위의 이런 서법 은 분명히 매우 불편 하 다.일단 쓰 는 것 을 잊 어 버 리 면 메모리 가 새 어 나 갈 것 이다.
    WeakMap 은 이 문 제 를 해결 하기 위해 탄생 한 것 입 니 다. 키 이름 이 인용 한 대상 은 모두 약 한 인용 입 니 다. 즉, 쓰레기 회수 체 제 는 이 인용 을 고려 하지 않 습 니 다.따라서 인 용 된 대상 의 다른 인용 이 모두 제거 되면 쓰레기 회수 메커니즘 은 이 대상 이 차지 하 는 메모 리 를 방출 한다.필요 하지 않 으 면 WeakMap 의 키 대상 과 해당 하 는 키 쌍 이 자동 으로 사라 지고 인용 을 수 동 으로 삭제 하지 않 아 도 된다 는 것 이다.
    WeakMap 의 구조:
    ES6 의 WeakMap 형식 은 키 가 맞 는 무질서 한 목록 입 니 다. 그 중에서 키 는 비어 있 지 않 은 대상 이 어야 하고 값 은 임의의 형식 으로 허용 합 니 다.WeakMap 의 인 터 페 이 스 는 Map 과 매우 비슷 합 니 다. / WeakMap 은 set 방법 으로 멤버 를 추가 할 수 있 습 니 다.
    const wm1 = new WeakMap();
    const key = {foo: 1};
    wm1.set(key, 2);
    wm1.get(key) // 2
    

    / / WeakMap 도 하나의 배열 을 받 아들 일 수 있 습 니 다. / / 구조 함수 로 서 의 매개 변수 입 니 다.
    const k1 = [1, 2, 3];
    const k2 = [4, 5, 6];
    const wm2 = new WeakMap([[k1, 'foo'], [k2, 'bar']]);
    wm2.get(k2) // "bar"
    

    WeakMap 의 속성 과 방법:
    WeakMap 과 Map 의 API 차 이 는 주로 두 가지 입 니 다. 하 나 는 반복 작업 (즉, keys (), values (), entries () 방법 이 없고 size 속성 도 없습니다.모든 키 이름 을 표시 할 방법 이 없 기 때문에, 어떤 키 이름 이 존재 하 는 지 는 전혀 예측 할 수 없 으 며, 쓰레기 회수 메커니즘 의 운행 여부 와 관련 이 있 습 니 다.이 순간 키 이름 을 찾 을 수 있 습 니 다. 다음 순간 쓰레기 회수 메커니즘 이 갑자기 실행 되 었 습 니 다. 이 키 이름 은 사 라 졌 습 니 다. 불확실 성 이 발생 하지 않도록 키 이름 을 찾 을 수 없 도록 통일 적 으로 규정 합 니 다.둘 째 는 클 리 어 방법 을 지원 하지 않 는 다 는 것 이다.따라서 WeakMap 은 get (), set (), has (), delete () 등 네 가지 방법 만 사용 할 수 있 습 니 다.
    const wm = new WeakMap();
    // size、forEach、clear       
    wm.size // undefined
    wm.forEach // undefined
    wm.clear // undefined
    

    WeakMap 상용 장면
    Weak Map 의 가장 좋 은 용 도 는 브 라 우 저 에서 특정 DOM 요소 와 연 결 된 대상 을 만 드 는 것 입 니 다.예 를 들 어 웹 페이지 에 사용 되 는 JS 라 이브 러 리 는 사용자 정의 대상 을 유지 하고 이 라 이브 러 리 에서 사용 하 는 모든 DOM 요 소 를 참조 하 며 매 핑 관 계 는 내부 대상 캐 시 에 저 장 됩 니 다.이 방법의 어려움 은 DOM 요소 가 웹 페이지 에 저장 되 지 않 고 이 라 이브 러 리 가 이 요소 의 관련 대상 을 제거 할 수 있 도록 어떻게 판단 하 느 냐 하 는 것 이다.이 라 이브 러 리 는 DOM 요소 에 대한 잘못된 인용 을 계속 유지 하고 메모리 누 출 을 초래 합 니 다.Weak Map 을 사용 하여 DOM 요 소 를 추적 합 니 다. 사용자 정의 대상 을 모든 DOM 요소 와 연결 할 수 있 습 니 다. 이 대상 과 연 결 된 DOM 요소 가 존재 하지 않 을 때 Weak Map 에서 자동 으로 삭 제 됩 니 다.주의해 야 할 것 은 Weak Map 의 키 가 약 한 인용 이지 값 이 아 닙 니 다.Weak Map 의 값 에 저장 대상 은 쓰레기 수 거 를 막 습 니 다. 이 대상 의 다른 인용 이 모두 제거 되 었 더 라 도.
    Weak Map 을 사용 할 지 정규 Map 을 사용 할 지 결정 할 때 가장 중요 한 요 소 는 대상 유형의 키 만 사용 하고 싶 은 지 여부 다.만약 네가 이렇게 하려 고 한다 면, 가장 좋 은 선택 은
    Weak Map 。추가 데이터 가 더 이상 사용 되 지 않 은 후에 소각 되 는 것 을 확보 하여 메모리 사용 을 최적화 시 키 고 메모리 누 출 을 피 할 수 있 기 때문이다.Weak Map 을 기억 하 세 요.
    콘 텐 츠 에 만 작은 보 기 를 제공 하기 때문에 foreach () 방법, size 속성 또는 clear () 를 사용 할 수 없습니다.
    방법 으로 그 중의 항목 을 관리 하 다.만약 당신 이 확실히 검사 기능 이 필요 하 다 면, 정규 맵 은 더 좋 은 선택 이 될 것 입 니 다. 다만 메모리 사용 에 유의 해 야 합 니 다.

    좋은 웹페이지 즐겨찾기