之前的 Set 和 Map

对象模拟 Set:

let obj = Object.create(null); // 创建的对象原型为 null
obj.v = true;
if (obj.v) // 判断值是否存在

模拟 Map:

let obj = Object.create(null);
obj.key = "value";
let v = obj.key; // "value"

变通方法问题

对象使用的任何类型的属性(键)实际上都会转换成对应的字符串类型作为键。

in 运算符根据某个属性是否存在于对象中返回 true 或 false,该运算符会搜索对象的原型。

Set

Set 的创建

let set = new Set();
set.add(1);
set.add("1");
set.size; // 2

let o1 = {},
    o2 = {};
set.add([o1, o2]);
set.size; // 3,数组中重复元素去除

let s1 = new Set();
s1.add(o1);
s1.add(o2);
s1.size; // 2

has(v) 判断传入的值是否存在于 Set 中,返回对应的布尔值。
delete(v) 从 Set 中删除指定值。
clear() 清空 Set 中所有的值。

forEach() 方法接收一个回调函数和一个可选的 this。回调函数有三个参数:第一个和第二个参数都表示 Set 中的元素,第三个参数表示 Set 本身。如果想在回调函数中使用 this, 则需要将 this 作为 forEach() 方法的第二个参数传入。当回调函数是箭头函数时,直接使用 this,不需要以任何方式传入到 forEach() 方法中。

使用扩展运算符可以将 Set 转换成数组。

let s = new Set([1,2]);
let arr = [...s]; // [1, 2]

WeakSet 只能存储对象的弱引用,不能存储基本类型值。弱引用表示如果对象仅存在弱引用这一个引用时,不会阻止垃圾回收器回收该对象,也就是某种意义上相当于该对象不存在引用了。

let s = new WeakSet(),
    k = {};
s.add(k);
s.has(k); // true

s.delete(k);
s.has(k); // false

k = null; // 此时对象没有强引用了,该对象会从 WeakSet 中移除。

WeakSet 的特点:

  • add() 方法传入非对象参数时会报错
  • 不可迭代
  • 没有 forEach() 方法
  • 没有 size 属性。

Map

Map 是存储键值对的有序列表。其中,键、值都可以为任意类型,键的类型不会自动发生转换。

let m = new Map();
let k1 = {};
let k2 = {};
m.set("k", "v");
m.set(k1, 1);
m.set(k2, true);

m.get("k"); // "v"
m.get(k1);  // 1
m.get(k2);  // true
m.get(a);   // undefined

has() 方法判断指定键是否在 Map 中。
delete() 方法删除指定键及其关联的值。
clear() 清空 Map 中所有的键值对。
size 属性存储 Map 中当前的键值对数量。

使用数组初始化 Map 时,该数组中的元素必须是长度为 2 的数组,其中第一个值作为键,第二个值作为键对应的值。

forEach() 方法接收一个回调函数和一个可选的 this。回调函数有三个参数,第一个参数表示值,第二个参数表示值对应的键,第三个参数表示 Map 本身。迭代的次序是添加到 Map 中的先后次序。

Weak Map 中的键必须是对象,这个引用是弱引用,而键对应的值不是。键对象没有强引用时,该键及其对应的值都会从 Weak Map 中移除。

Weak Map 是以键值对作为元素的无序列表,键必须是非空对象,而值可以为任意类型。Weak Map 使用数组初始化的方式与 Map 一样。
Weak Map 与 Map 相比,没有 clear() 方法,没有 size 属性。
Weak Map 的弱引用对象可以很好地做到对象销毁时,私有数据也会随之销毁。

let Per = (function() {
  let privateData = new WeakMap();

  function Per(name) {
    privateData.set(this, {name: name});
  }

  Per.prototype.getName = function() {
    return privateData.get(this).name;
  };

  return Per;
}());

只允许键的类型为对象类型时,使用 Weak Map;否则使用 Map。另外,如果想使用 Weak Map 没有提供的方法,那只能使用 Map。

参考

[1] Zakas, Understanding ECMAScript 6, 2017.

 posted on 2024-05-17 20:33  x-yun  阅读(2)  评论(0编辑  收藏  举报