Twlig / issuesBlog

MIT License
3 stars 0 forks source link

映射与弱映射、集合与弱集合 #26

Open Twlig opened 2 years ago

Twlig commented 2 years ago

Map

Map 是一种新的集合类型,是真正的键/值存储机制。

初始化

实例方法

  1. size

    获取Map实例映射的键值对数量

    alert(m1.size); // 3
  2. has()

    判断是否存在该键。传入一个参数,返回布尔值。

    Map 内部使用 SameValueZero 比较操作(ECMAScript 规范内部定义,语言中不能使用),基本上相当于使用严格对象相等的标准来检查键的匹配性。

    m1.has("key1") //true
  3. set()

    添加键/值对。

    接收两个参数:参数一键,参数二值。

    set()方法返回映射实例,因此可以把多个操作连缀起来,包括初始化声明。

    const m = new Map()
    .set("firstName", "Matt") 
    .set("lastName", "Frisbie");
  4. get()

    查询键对应的值。接收一个参数:待查询的键。使用 SameValueZero 比较操作。

    m.get("firstName")  //Matt
  5. delete()

    删除键对应的键值对。接收一个参数:待删除的键。使用 SameValueZero 比较操作。

    m.delete("firstName");
    //m : {'lastName' => 'Frisbie'}
  6. clear()

    清除映射中的所有键值对。

    m.clear()  //Map(0)

迭代

Map映射实例可以提供一个迭代器(Iterator),能以插入顺序生成[key, value]形式的数组。可以通过 entries()方法或者 Symbol.iterator 属性取得这个迭代器。

  1. Symbol.iterator 属性

    const m = new Map([ 
    ["key1", "val1"], 
    ["key2", "val2"], 
    ["key3", "val3"] 
    ]);
    for (let pair of m[Symbol.iterator]()) { 
    alert(pair); 
    }
    // [key1,val1] 
    // [key2,val2] 
    // [key3,val3]
  2. entries()

    for (let pair of m.entries()) { 
    alert(pair); 
    }
    // [key1,val1] 
    // [key2,val2] 
    // [key3,val3]
  3. keys()、values()

    for (let key of m.keys()) { 
    alert(key); 
    } 
    // key1 
    // key2 
    // key3 
    for (let key of m.values()) { 
    alert(key); 
    } 
    // value1 
    // value2 
    // value3

注意

键是对象的话,属性是可以修改的,映射关系不会变。如果是字符串、数字等就不能修改,没有修改的接口。

const keyObj = {id: 1};
const m = new Map([ 
 [keyObj, "val1"] 
]); 
// 修改了作为键的对象的属性,但对象在映射内部仍然引用相同的值
for (let key of m.keys()) { 
 key.id = "newKey"; 
 alert(key); // {id: "newKey"} 
 alert(m.get(keyObj)); // val1   键值对的映射关系没变
} 
alert(keyObj); // {id: "newKey"}

WeakMap

“弱映射”(WeakMap)是一种新的集合类型,其 API 也是 Map 的子集。“weak”(弱)指的是 JavaScript 垃圾回收程序对待“弱映射”中键的方式。

特性

实例方法

WeakMap只有set,get,has,delete方法。没有迭代能力,其不可能在不知道对象引用的情况下从弱映射中取得值。当然也就没有clear方法。

案例说明

const wm = new WeakMap(); 
wm.set({}, "val"); 
const wm = new WeakMap(); 
const container = { 
 key: {} 
}; 
wm.set(container.key, "val"); 
function removeReference() { 
 container.key = null; 
}

应用场景

小结

WeakMap主要的用途就是便于垃圾回收,由于WeakMap中对键的引用是弱引用,不会阻止垃圾回收,所以当键指向的对象不在了(即没有除WeakMap外的其他变量引用该对象),WeakMap中的键值对映射关系也就销毁了。

Set

Set 是一种新集合类型。

初始化

实例方法

  1. size

    获取集合元素数量

    alert(s1.size); // 3
  2. has()

    判断是否存在该元素。传入一个参数,返回布尔值。

    使用 SameValueZero 比较操作(ECMAScript 规范内部定义,语言中不能使用),基本上相当于使用严格对象相等的标准来检查键的匹配性。

    s1.has("val1") //true
  3. add()

    添加元素。

    add()方法返回集合实例,因此可以把多个操作连缀起来,包括初始化声明。

    const s = new Map()
    .add("val1") 
    .add("val2");
  4. delete()

    删除元素。使用 SameValueZero 比较操作。返回一个布尔值,表示集合中是否存在要删除的值。

    s.delete("val1");
  5. clear()

    销毁集合实例中的所有值。

    s.clear()  

迭代

集合实例可以提供一个迭代器(Iterator),能以插入顺序生成集合内容。可以通过 values()方法及其别名方法 keys()(或者 Symbol.iterator 属性,它引用 values())取得这个迭代器。

  1. Symbol.iterator 属性

    const s = new Set(["val1", "val2", "val3"]);
    for (let value of s[Symbol.iterator]()) { 
    alert(value); 
    } 
    // val1 
    // val2 
    // val3
  2. keys()、values()

    for (let value of s.keys()) { 
    alert(key); 
    } 
    // val1 
    // val2 
    // val3
    for (let value of s.values()) { 
    alert(value); 
    } 
    // val1 
    // val2 
    // val3
  3. entries()

    集合的 entries()方法返回一个迭代器,可以按照插入顺序产生包含两个元素的数组,这两个元素是集合中每个值的重复出现

    const s = new Set(["val1", "val2", "val3"]); 
    for (let pair of s.entries()) { 
    console.log(pair); 
    } 
    // ["val1", "val1"] 
    // ["val2", "val2"] 
    // ["val3", "val3"]

WeakSet

“弱集合”(WeakSet)是一种新的集合类型。WeakSet 中的“weak”(弱),描述的是 JavaScript 垃圾回收程序对待“弱集合”中值的方式。这些值不属于正式的引用,不会阻止垃圾回收。

特性

实例方法

有add,has,delete方法,没有clear方法。

案例说明

const ws = new WeakSet(); 
ws.add({});

add()方法初始化了一个新对象,并将它用作一个值。因为没有指向这个对象的其他引用,所以当这行代码执行完成后,这个对象值就会被当作垃圾回收。然后,这个值就从弱集合中消失了,使其成为一个空集合。

const ws = new WeakSet(); 
const container = { 
 val: {} 
}; 
ws.add(container.val); 
function removeReference() { 
 container.val = null; 
}

这一次,container 对象维护着一个对弱集合值的引用,因此这个对象值不会成为垃圾回收的目标。不过,如果调用了 removeReference(),就会摧毁值对象的最后一个引用,垃圾回收程序就可以把这个值清理掉。

使用场景

加入对应集合,给节点打上“禁用”标签。通过查询元素在不在 disabledElements 中,就可以知道它是不是被禁用了。只要 WeakSet 中任何元素从 DOM 树中被删除,垃圾回收程序就可以忽略其存在,而立即释放其内存(假设没有其他地方引用这个对象)

const disabledElements = new WeakSet(); 
const loginButton = document.querySelector('#login'); 
// 通过加入对应集合,给这个节点打上“禁用”标签
disabledElements.add(loginButton);