转载:Set ,WeakSet和 Map,WeakMap 数据结构

由于这篇文章是引用过来的,调整了很久还是没有达到原文章的效果,与此同时我也附上了原文的地址,需要的可以点击查看

目录

Set

基本用法

Set函数初始化

Set函数传值

传基本类型

Set 实例的属性和方法

Set注意点

WeakSet

WeakSet 含义

WeakSet原理

WeakSet 使用

WeakSet 方法

WeakSet 注意点

map

map含义

map构造函数传参

传对象

传数组

map注意点

Map实例的属性和操作方法

遍历方法

与其他数据结构的互相转换

WeakMap

含义

WeakMap与Map的区别

WeakMap的方法

WeakMap 的用途

总结


参考网站:

http://es6.ruanyifeng.com/#docs/set-map

Set

ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。

基本用法

Set本身是一个构造函数,用来生成 Set 数据结构(即set方法返回的就是set数据)。跟foreach搭配可以去重


 
 
  1. const s = new Set();
  2. [ 2, 3, 5, 4, 5, 2, 2].forEach( x => s.add(x)); // add()方法向 Set 结构加入成员,生成 Set 数据结构。
  3. for ( let i of s) {
  4. console.log(i);
  5. }
  6. // 2 3 5 4 // 结果表明 Set 结构不会添加重复的值。

去除数组重复成员的方法。


 
 
  1. // 去除数组的重复成员
  2. let a=[...new Set([ 1, 2, 3, 3, 3, 4])]
  3. // a=[1,2,3,4] // 扩展运算符跟Array.from一样都可以吧set数据转换为数组

去除字符串里面的重复字符。


 
 
  1. [...new Set( 'ababbc')].join( '')
  2. // "abc"

Set函数初始化

Set函数可以接受一个数组(或者具有 iterable 接口的其他数据结构)作为参数,用来初始化。


 
 
  1. // 例一
  2. const set = new Set([ 1, 2, 3, 4, 4]);
  3. [... set]
  4. // [1, 2, 3, 4]
  5. // 例二
  6. const items = new Set([ 1, 2, 3, 4, 5, 5, 5, 5]);
  7. items.size // 5 // 去除数组重复成员
  8. // 例三
  9. const set = new Set(document.querySelectorAll( 'div'));
  10. set.size // 56
  11. // 类似于
  12. const set = new Set();
  13. document
  14. .querySelectorAll( 'div')
  15. .forEach( div => set.add( div));
  16. set.size // 56

Set函数传值

传基本类型

向 Set 加入值的时候,不会发生类型转换,所以5"5"是两个不同的值。

Set 内部判断两个值是否不同,使用的算法叫做“Same-value-zero equality”,它类似于精确相等运算符(===),主要的区别是NaN等于自身,而精确相等运算符认为NaN不等于自身。


 
 
  1. let set = new Set();
  2. let a = NaN;
  3. let b = NaN;
  4. set.add(a);
  5. set.add(b);
  6. set // Set { NaN} //向 Set 实例添加了两个 NaN,但是只能加入一个。
  7. //这表明,在 Set 内部,两个 NaN是相等。

传引用类型

两个对象总是不相等的。


 
 
  1. let set = new Set();
  2. set. add({});
  3. set.size // 1
  4. set. add({});
  5. set.size // 2 // 由于两个空对象不相等,所以它们被视为两个值

Set 实例的属性和方法

Set 结构的实例有以下属性。

  • Set.prototype.constructor:构造函数,默认就是Set函数。
  • Set.prototype.size:返回Set实例的成员总数。

Set 实例的方法分为两大类:操作方法(用于操作数据)和遍历方法(用于遍历成员)。

下面先介绍四个操作方法。

  • add(value):添加某个值,返回 Set 结构本身。
  • delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
  • has(value):返回一个布尔值,表示该值是否为Set的成员。
  • clear():清除所有成员,没有返回值。

 
 
  1. s. add( 1). add( 2). add( 2);
  2. // 注意2被加入了两次
  3. s.size // 2
  4. s.has( 1) // true
  5. s.has( 2) // true
  6. s.has( 3) // false
  7. s.delete( 2);
  8. s.has( 2) // false

Set 结构的实例有四个遍历方法,可以用于遍历成员。

  • keys():返回键名的遍历器
  • values():返回键值的遍历器
  • entries():返回键值对的遍历器
  • forEach():使用回调函数遍历每个成员

Set的遍历顺序就是插入顺序。

(1)keys()values()entries()

keys方法、values方法、entries方法返回的都是遍历器对象(详见《Iterator 对象》一章)。由于 Set 结构没有键名,只有键值(或者说键名和键值是同一个值),所以keys方法和values方法的行为完全一致。


 
 
  1. let set = new Set([ 'red', 'green', 'blue']);
  2. for ( let item of set.keys()) {
  3. console.log(item);
  4. }
  5. // red
  6. // green
  7. // blue
  8. for ( let item of set.values()) {
  9. console.log(item);
  10. }
  11. // red
  12. // green
  13. // blue
  14. for ( let item of set.entries()) { // entries方法返回的遍历器,同时包括键名和键值
  15. console.log(item);
  16. }
  17. // ["red", "red"]
  18. // ["green", "green"]
  19. // ["blue", "blue"]

Set 结构的实例默认可遍历,它的默认遍历器生成函数就是它的values方法。


 
 
  1. Set.prototype[ Symbol.iterator] === Set.prototype.values
  2. // true

这意味着,可以省略values方法,可直接用for...of循环遍历 Set。


 
 
  1. let set = new Set([ 'red', 'green', 'blue']);
  2. for ( let x of set) {
  3. console.log(x);
  4. }
  5. // red
  6. // green
  7. // blue

(2)forEach()

Set 结构的实例与数组一样,也拥有forEach方法,用于对每个成员执行某种操作,没有返回值。


 
 
  1. let set = new Set([ 1, 4, 9]);
  2. set.forEach( (value, key) => console.log(key + ' : ' + value))
  3. // 1 : 1
  4. // 4 : 4
  5. // 9 : 9

上面代码说明,forEach方法的参数就是一个处理函数。该函数的参数与数组的forEach一致,依次为键值、键名、集合本身(上例省略了该参数)。这里需要注意,Set 结构的键名就是键值(两者是同一个值),因此第一个参数与第二个参数的值永远都是一样的。

另外,forEach方法还可以有第二个参数,表示绑定处理函数内部的this对象。

(3)遍历的应用

扩展运算符(...)内部使用for...of循环,所以也可以用于 Set 结构。


 
 
  1. let set = new Set([ 'red', 'green', 'blue']);
  2. let arr = [... set];
  3. // [ 'red', 'green', 'blue']

扩展运算符和 Set 结构相结合,就可以去除数组的重复成员。


 
 
  1. let arr = [ 3, 5, 2, 2, 5, 5];
  2. let unique = [...new Set(arr)];
  3. // [3, 5, 2]

而且,数组的mapfilter方法也可以间接用于 Set 了。


 
 
  1. let set = new Set([ 1, 2, 3]);
  2. set = new Set([...set].map(x => x * 2));
  3. // 返回 Set结构:{ 2, 4, 6}
  4. let set = new Set([ 1, 2, 3, 4, 5]);
  5. set = new Set([...set].filter(x => (x % 2) == 0));
  6. // 返回 Set结构:{ 2, 4}

因此使用 Set 可以很容易地实现并集(Union)、交集(Intersect)和差集(Difference)。


 
 
  1. let a = new Set([ 1, 2, 3]);
  2. let b = new Set([ 4, 3, 2]);
  3. // 并集
  4. let union = new Set([...a, ...b]);
  5. // Set {1, 2, 3, 4}
  6. // 交集
  7. let intersect = new Set([...a].filter( x => b.has(x)));
  8. // set {2, 3}
  9. // 差集
  10. let difference = new Set([...a].filter( x => !b.has(x)));
  11. // Set {1}

如果想在遍历操作中,同步改变原来的 Set 结构,目前没有直接的方法,但有两种变通方法。一种是利用原 Set 结构映射出一个新的结构,然后赋值给原来的 Set 结构;另一种是利用Array.from方法。


 
 
  1. // 方法一
  2. let set = new Set([ 1, 2, 3]);
  3. set = new Set([...set].map(val => val * 2));
  4. // set的值是 2, 4, 6
  5. // 方法二
  6. let set = new Set([ 1, 2, 3]);
  7. set = new Set(Array.from( set, val => val * 2));
  8. // set的值是 2, 4, 6

上面代码提供了两种方法,直接在遍历操作中改变原来的 Set 结构。

Set注意点

1.看看在判断是否包括一个键上面,Object结构和Set结构的写法不同。


 
 
  1. // 对象的写法
  2. const properties = {
  3. 'width': 1,
  4. 'height': 1
  5. };
  6. if (properties[someName]) { //直接判断属性
  7. // do something
  8. }
  9. // Set的写法
  10. const properties = new Set();
  11. properties. add( 'width');
  12. properties. add( 'height');
  13. if (properties.has(someName)) { //通过has方法判断
  14. // do something
  15. }

2.Array.from方法可以将 Set 结构转为数组。


 
 
  1. const items = new Set([ 1, 2, 3, 4, 5]);
  2. const array = Array.from(items);

这就提供了去除数组重复成员的另一种方法。


 
 
  1. function dedupe(array) {
  2. return Array.from( new Set(array));
  3. }
  4. dedupe([ 1, 1, 2, 3]) // [1, 2, 3]

WeakSet

WeakSet 含义

WeakSet 结构与 Set 类似,也是不重复的值的集合。但是,它与 Set 有两个区别。

首先,WeakSet 的成员只能是对象,而不能是其他类型的值。


 
 
  1. const ws = new WeakSet();
  2. ws.add( 1)
  3. // TypeError: Invalid value used in weak set
  4. ws.add( Symbol())
  5. // TypeError: invalid value used in weak set

WeakSet原理


 
 
  1. const foos = new WeakSet()
  2. class Foo {
  3. constructor() {
  4. foos.add( this)
  5. }
  6. method () {
  7. if (!foos.has( this)) {
  8. throw new TypeError( 'Foo.prototype.method 只能在Foo的实例上调用!');
  9. }
  10. }
  11. }

上面代码保证了Foo的实例方法,只能在Foo的实例上调用。这里使用 WeakSet 的好处是,foos对实例的引用,不会被计入内存回收机制,所以删除实例的时候,不用考虑foos,也不会出现内存泄漏。

WeakSet 使用

WeakSet 是一个构造函数,可以使用new命令,创建 WeakSet 数据结构。

const ws = new WeakSet();
 
 

作为构造函数,WeakSet 可以接受一个数组或类似数组的对象作为参数。(实际上,任何具有 Iterable 接口的对象,都可以作为 WeakSet 的参数。)该数组的所有成员,都会自动成为 WeakSet 实例对象的成员。


 
 
  1. const a = [[ 1, 2], [ 3, 4]];
  2. const ws = new WeakSet(a);
  3. // WeakSet {[1, 2], [3, 4]} // 是a数组的成员成为 WeakSet 的成员,而不是a数组本身。
  4. // 这意味着,数组的成员只能是对象。

WeakSet 方法

  • WeakSet.prototype.add(value):向 WeakSet 实例添加一个新成员。
  • WeakSet.prototype.delete(value):清除 WeakSet 实例的指定成员。
  • WeakSet.prototype.has(value):返回一个布尔值,表示某个值是否在 WeakSet 实例之中。

 
 
  1. const ws = new WeakSet();
  2. const obj = {};
  3. const foo = {};
  4. ws.add( window);
  5. ws.add(obj);
  6. ws.has( window); // true
  7. ws.has(foo); // false
  8. ws.delete( window);
  9. ws.has( window); // false

WeakSet 注意点

1.WeakSet 没有size属性和forEach方法,没有办法遍历它的成员。

原因:

WeakSet 不能遍历,是因为成员都是弱引用,随时可能消失,遍历机制无法保证成员的存在,很可能刚刚遍历结束,成员就取不到了。WeakSet 的一个用处,是储存 DOM 节点,而不用担心这些节点从文档移除时,会引发内存泄漏。

map

map含义

JavaScript 的对象(Object),本质上是键值对的集合(Hash 结构),但是传统上只能用字符串当作键。这给它的使用带来了很大的限制。

ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。如果你需要“键值对”的数据结构,Map 比 Object 更合适。

map构造函数传参

传对象


 
 
  1. const m = new Map();
  2. const o = {p: 'Hello World'};
  3. m. set(o, 'content')
  4. m. get(o) // "content"
  5. m.has(o) // true
  6. m.delete(o) // true
  7. m.has(o) // false

传数组


 
 
  1. const map = new Map([
  2. [ 'name', '张三'],
  3. [ 'title', 'Author']
  4. ]);
  5. map.size // 2
  6. map.has( 'name') // true
  7. map.get( 'name') // "张三"
  8. map.has( 'title') // true
  9. map.get( 'title') // "Author"

Map构造函数接受数组作为参数,实际上执行的是下面的算法。


 
 
  1. const items = [
  2. [ 'name', '张三'],
  3. [ 'title', 'Author']
  4. ];
  5. const map = new Map();
  6. items.forEach(
  7. ([key, value]) => map.set(key, value)
  8. );

map注意点

1.如果对同一个键多次赋值,后面的值将覆盖前面的值。


 
 
  1. const map = new Map();
  2. map
  3. .set( 1, 'aaa')
  4. .set( 1, 'bbb');
  5. map.get( 1) // "bbb" 后一次的值覆盖前一次的值

2.如果读取一个未知的键,则返回undefined


 
 
  1. new Map().get( 'asfddfsasadf')
  2. // undefined

3.只有对同一个对象的引用,Map 结构才将其视为同一个键。这一点要非常小心。


 
 
  1. const map = new Map();
  2. map. set([ 'a'], 555);
  3. map.get([ 'a']) // undefined // 原因是set的['a']和get的['a']都是对象,所以指针(内存地址不一样),所以取不到值
  4. // 修改后
  5. const map = new Map();
  6. const k1 = [ 'a'];
  7. map. set(k1, 111)
  8. map.get(k1) // 111

4.同样的值的两个实例,在 Map 结构中被视为两个键。


 
 
  1. const map = new Map();
  2. const k1 = [ 'a'];
  3. const k2 = [ 'a'];
  4. map
  5. . set(k1, 111)
  6. . set(k2, 222);
  7. map.get(k1) // 111
  8. map.get(k2) // 222

5.Map 的键是一个简单类型的值(数字、字符串、布尔值),则只要两个值严格相等,Map 将其视为一个键,比如

  • 0-0就是一个键,
  • 布尔值true和字符串true则是两个不同的键
  • undefinednull也是两个不同的键
  • 虽然NaN不严格相等于自身,但 Map 将其视为同一个键

 
 
  1. let map = new Map();
  2. map. set(- 0, 123);
  3. map. get(+ 0) // 123
  4. map. set( true, 1);
  5. map. set(' true', 2);
  6. map. get( true) // 1
  7. map. set(undefined, 3);
  8. map. set(null, 4);
  9. map. get(undefined) // 3
  10. map. set( NaN, 123);
  11. map. get( NaN) // 123

Map实例的属性和操作方法

Map 结构的实例有以下属性和操作方法。

(1)size 属性

size属性返回 Map 结构的成员总数。


 
 
  1. const map = new Map();
  2. map.set( 'foo', true);
  3. map.set( 'bar', false);
  4. map.size // 2

(2)set(key, value)

set方法设置键名key对应的键值为value,然后返回整个 Map 结构。如果key已经有值,则键值会被更新,否则就新生成该键。


 
 
  1. const m = new Map();
  2. m. set( 'edition', 6) // 键是字符串
  3. m. set( 262, 'standard') // 键是数值
  4. m. set(undefined, 'nah') // 键是 undefined

set方法返回的是当前的Map对象,因此可以采用链式写法。


 
 
  1. let map = new Map()
  2. . set( 1, 'a')
  3. . set( 2, 'b')
  4. . set( 3, 'c');

(3)get(key)

get方法读取key对应的键值,如果找不到key,返回undefined


 
 
  1. const m = new Map();
  2. const hello = function() { console.log( 'hello');};
  3. m.set(hello, 'Hello ES6!') // 键是函数
  4. m.get(hello) // Hello ES6!

(4)has(key)

has方法返回一个布尔值,表示某个键是否在当前 Map 对象之中。


 
 
  1. const m = new Map();
  2. m.set( 'edition', 6);
  3. m.set( 262, 'standard');
  4. m.set( undefined, 'nah');
  5. m.has( 'edition') // true
  6. m.has( 'years') // false
  7. m.has( 262) // true
  8. m.has( undefined) // true

(5)delete(key)

delete方法删除某个键,返回true。如果删除失败,返回false


 
 
  1. const m = new Map();
  2. m.set( undefined, 'nah');
  3. m.has( undefined) // true
  4. m.delete( undefined)
  5. m.has( undefined) // false

(6)clear()

clear方法清除所有成员,没有返回值。


 
 
  1. let map = new Map();
  2. map.set( 'foo', true);
  3. map.set( 'bar', false);
  4. map.size // 2
  5. map.clear()
  6. map.size // 0

遍历方法

Map 结构原生提供三个遍历器生成函数和一个遍历方法。

  • keys():返回键名的遍历器。
  • values():返回键值的遍历器。
  • entries():返回所有成员的遍历器。
  • forEach():遍历 Map 的所有成员。

需要特别注意的是,Map 的遍历顺序就是插入顺序。


 
 
  1. const map = new Map([
  2. [ 'F', 'no'],
  3. [ 'T', 'yes'],
  4. ]);
  5. for ( let key of map.keys()) {
  6. console.log(key);
  7. }
  8. // "F"
  9. // "T"
  10. for ( let value of map.values()) {
  11. console.log(value);
  12. }
  13. // "no"
  14. // "yes"
  15. for ( let item of map.entries()) {
  16. console.log(item[ 0], item[ 1]);
  17. }
  18. // "F" "no"
  19. // "T" "yes"
  20. // 或者
  21. for ( let [key, value] of map.entries()) {
  22. console.log(key, value);
  23. }
  24. // "F" "no"
  25. // "T" "yes"
  26. // 等同于使用map.entries()
  27. for ( let [key, value] of map) {
  28. console.log(key, value);
  29. }
  30. // "F" "no"
  31. // "T" "yes"

上面代码最后的那个例子,表示 Map 结构的默认遍历器接口(Symbol.iterator属性),就是entries方法。


 
 
  1. map[Symbol.iterator] === map.entries
  2. // true

Map 结构转为数组结构,比较快速的方法是使用扩展运算符(...)。


 
 
  1. const map = new Map([
  2. [ 1, 'one'],
  3. [ 2, 'two'],
  4. [ 3, 'three'],
  5. ]);
  6. [... map.keys()]
  7. // [1, 2, 3]
  8. [... map.values()]
  9. // ['one', 'two', 'three']
  10. [... map.entries()]
  11. // [[1,'one'], [2, 'two'], [3, 'three']]
  12. [... map]
  13. // [[1,'one'], [2, 'two'], [3, 'three']]

结合数组的map方法、filter方法,可以实现 Map 的遍历和过滤(Map 本身没有mapfilter方法)。


 
 
  1. const map0 = new Map()
  2. .set( 1, 'a')
  3. .set( 2, 'b')
  4. .set( 3, 'c');
  5. const map1 = new Map(
  6. [...map0].filter( ([k, v]) => k < 3)
  7. );
  8. // 产生 Map 结构 {1 => 'a', 2 => 'b'}
  9. const map2 = new Map(
  10. [...map0].map( ([k, v]) => [k * 2, '_' + v])
  11. );
  12. // 产生 Map 结构 {2 => '_a', 4 => '_b', 6 => '_c'}

此外,Map 还有一个forEach方法,与数组的forEach方法类似,也可以实现遍历。


 
 
  1. map.forEach( function(value, key, map) {
  2. console.log( "Key: %s, Value: %s", key, value);
  3. });

forEach方法还可以接受第二个参数,用来绑定this


 
 
  1. const reporter = {
  2. report: function(key, value) {
  3. console.log( "Key: %s, Value: %s", key, value);
  4. }
  5. };
  6. map.forEach( function(value, key, map) {
  7. this.report(key, value);
  8. }, reporter); // 第二个参数使forEach方法的回调函数的this,就指向reporter。

 

与其他数据结构的互相转换

(1)Map 转为数组

前面已经提过,Map 转为数组最方便的方法,就是使用扩展运算符(...)。


 
 
  1. const myMap = new Map()
  2. . set( true, 7)
  3. . set({foo: 3}, [ 'abc']);
  4. [ ...myMap]
  5. // [ [ true, 7 ], [ { foo: 3 }, [ 'abc' ] ] ]

(2)数组 转为 Map

将数组传入 Map 构造函数,就可以转为 Map。


 
 
  1. new Map([
  2. [ true, 7],
  3. [{ foo: 3}, [ 'abc']]
  4. ])
  5. // Map {
  6. // true => 7,
  7. // Object {foo: 3} => ['abc']
  8. // }

(3)Map 转为对象

如果所有 Map 的键都是字符串,它可以无损地转为对象。


 
 
  1. function strMapToObj(strMap) {
  2. let obj = Object.create( null);
  3. for ( let [k,v] of strMap) {
  4. obj[k] = v;
  5. }
  6. return obj;
  7. }
  8. const myMap = new Map()
  9. .set( 'yes', true)
  10. .set( 'no', false);
  11. strMapToObj(myMap)
  12. // { yes: true, no: false }

如果有非字符串的键名,那么这个键名会被转成字符串,再作为对象的键名。

(4)对象转为 Map


 
 
  1. function objToStrMap(obj) {
  2. let strMap = new Map();
  3. for ( let k of Object.keys(obj)) {
  4. strMap.set(k, obj[k]);
  5. }
  6. return strMap;
  7. }
  8. objToStrMap({ yes: true, no: false})
  9. // Map {"yes" => true, "no" => false}

(5)Map 转为 JSON

Map 转为 JSON 要区分两种情况。一种情况是,Map 的键名都是字符串,这时可以选择转为对象 JSON。


 
 
  1. function strMapToJson(strMap) {
  2. return JSON.stringify(strMapToObj(strMap));
  3. }
  4. let myMap = new Map().set( 'yes', true).set( 'no', false);
  5. strMapToJson(myMap)
  6. // '{"yes":true,"no":false}'

另一种情况是,Map 的键名有非字符串,这时可以选择转为数组 JSON。


 
 
  1. function mapToArrayJson(map) {
  2. return JSON.stringify([...map]);
  3. }
  4. let myMap = new Map().set( true, 7).set({ foo: 3}, [ 'abc']);
  5. mapToArrayJson(myMap)
  6. // '[[true,7],[{"foo":3},["abc"]]]'

(6)JSON 转为 Map

JSON 转为 Map,正常情况下,所有键名都是字符串。


 
 
  1. function jsonToStrMap(jsonStr) {
  2. return objToStrMap( JSON.parse(jsonStr));
  3. }
  4. jsonToStrMap( '{"yes": true, "no": false}')
  5. // Map {'yes' => true, 'no' => false}

但是,有一种特殊情况,整个 JSON 就是一个数组,且每个数组成员本身,又是一个有两个成员的数组。这时,它可以一一对应地转为 Map。这往往是 Map 转为数组 JSON 的逆操作。


 
 
  1. function jsonToMap(jsonStr) {
  2. return new Map( JSON.parse(jsonStr));
  3. }
  4. jsonToMap( '[[true,7],[{"foo":3},["abc"]]]')
  5. // Map {true => 7, Object {foo: 3} => ['abc']}

 

WeakMap

含义

WeakMap结构与Map结构类似,也是用于生成键值对的集合。

WeakMapMap的区别

1.WeakMap只接受对象作为键名(null除外),不接受其他类型的值作为键名。


 
 
  1. const map = new WeakMap();
  2. map. set( 1, 2)
  3. // TypeError: 1 is not an object!
  4. map. set(Symbol(), 2)
  5. // TypeError: Invalid value used as weak map key
  6. map. set(null, 2)
  7. // TypeError: Invalid value used as weak map key

2.WeakMap的键名所指向的对象(弱引用),不计入垃圾回收机制。

正常写法


 
 
  1. const e1 = document.getElementById( 'foo');
  2. const e2 = document.getElementById( 'bar');
  3. const arr = [
  4. [e1, 'foo 元素'], // 这就形成了arr对e1和e2的引用。
  5. [e2, 'bar 元素'],
  6. ];
  7. // 不需要 e1 和 e2 的时候
  8. // 必须手动删除引用,一旦忘了写,就会造成内存泄露
  9. arr [ 0] = null;
  10. arr [ 1] = null;

WeakMap 就是为了解决这个问题而诞生的,它的键名所引用的对象都是弱引用,即垃圾回收机制不将该引用考虑在内。因此,只要所引用的对象的其他引用都被清除,垃圾回收机制就会释放该对象所占用的内存。也就是说,一旦不再需要,WeakMap 里面的键名对象和所对应的键值对会自动消失,不用手动删除引用。


 
 
  1. const wm = new WeakMap();
  2. const element = document.getElementById( 'example'); // element对象的引用计数是1
  3. wm.set(element, 'some information');
  4. wm.get(element) // "some information"
  5. // WeakMap 里面对element的引用就是弱引用,
  6. // 一旦消除对该节点的引用,它占用的内存就会被垃圾回收机制释放

3WeakMap 弱引用的只是键名,而不是键值。键值依然是正常引用。


 
 
  1. const wm = new WeakMap();
  2. let key = {};
  3. let obj = {foo: 1};
  4. wm. set(key, obj);
  5. obj = null;
  6. wm. get(key)
  7. // Object {foo: 1} //即使在 WeakMap 外部消除了obj的引用,WeakMap 内部的引用依然存在

WeakMap的方法

1.没有遍历方法clear()、keys()values()、entries()、size属性

2.只有get()set()has()delete()

WeakMap 的用途

 

总结

set数据就是遍历返回对象的键和值是同一个,唯一性可去重

map数据就是遍历返回对象的键和值是不同的,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值