es6 Set和WeakSet

发布时间:2019-08-10 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了es6 Set和WeakSet脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

Js大部分历史时期都只存在一种集合类型,也就是数组类型。数组在 JS 中的使用正如其他语言的数组一样,但缺少更多类型的集合导致数组也经常被当作队列与栈来使用。数组只使用了数值型的索引,而如果非数值型的索引是必要的,开发者便会使用非数组的对象。这种技巧引出了非数组对象的定制实现,即 Set 与 Map

Set:

Set概述

Set对象是值的集合,你可以按照插入的顺序迭代它的元素。 Set中的元素只会出现一次,即 Set 中的元素是唯一的。

 Set结构类似于数组,但是没有重复结构
 Set会自动移除重复的值,因此可以用来过滤数组中的重复结构
 Set内的对象是强引用

Set的构造:

a)    let set = new Set([1, 2, 3, 4]);

Set 构造器实际上可以接收任意可迭代对象作为参数。能使用数组是因为它们默认就是可迭代的,Set与Map也是一样,Set构造器会使用迭代器来提取参数中的值

b)    let set = new Set();

    set.add(1);
    set.add(2);
    set.add(2);
    //如果add对相同的值进行了多次调用,那么那么在第一次之后的调用实际上会被忽略
    set.add(3);
    set.add('3');

Set 不会使用强制类型转换来判断值是否重复。这意味着 Set 可以同时包含数值 3 与 字符串 "3" ,将它们都作为相对独立的项.
Set判断是否重复使用了Object.is() 方法,唯一的例外是 +0 与 -0 在 Set 中被判断为是相等的

c) 还可以向Set添加多个值相同的对象,他们不会被合并为同一项。

let set = new Set();
let key1 = {};
let key2 = {};
set.add(key1);
set.add(key2);

Set的属性及方法:

1、属性

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

2、方法

Set的方法分为两类:操作方法 和 遍历方法

2.1、操作方法:

add(value):添加某个值,返回 Set 结构本身。
  因为返回set本身,所以可以写成:
  set.add(1).add(2).add(3)

•delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
 set.delete(2) ; // true

•has(value):返回一个布尔值,表示该值是否为Set的成员。
 set.has(2) ; // false

•clear():清除所有成员,没有返回值。

2.2、遍历方法:

foreach():使用回调函数遍历每个成员

es5给数组添加了forEach()方法,使得更容易处理数组中的每一项,没有返回值
对于数组来说forEach的三个参数:
arr[].forEach(function(value,index,array){//do})
value数组中的当前项, index当前项的索引, array原始数组

但是对于Set来说:

  let set2 = new Set([{'a':1}, {'b':2}]);
    set2.forEach(function(value, key, ownerSet) {
      console.LOG(ownerSet === set2);
      console.log(value === key);
    });

key 与 value 总是相同的,同时 ownerSet 也始终等于 set 。此代码输出:
true
true
true
true

如果想在回调函数中使用当前的this,还可以在forEach中传入this作为第二个参数

let set = new Set([1, 2]);
let processor = {
    output(value) {
    console.log(value);
  },
  process(dataSet) {
    dataSet.forEach(function(value) {
      this.output(value);
    }, this);
  }
};
processor.process(set);

本例中,在Processor.process方法中的set调用了forEach方法,并传递了this作为第二个参数,这样便能正确的调用到this.output()方法
或者也可以使用箭头函数来达到相同的效果,无需传入this,只需将上边的process改写成:

process(dataSet) {
  dataSet.forEach((value) => this.output(value));
}
keys()、values()和entries()

keys():返回键名的遍历器
values():返回键值的遍历器
entries():返回键值对的遍历器

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

let set = new Set(['red', 'green', 'blue']);

for (let item of set.keys()) {
  console.log(item);
}
// red
// green
// blue

for (let item of set.values()) {
  console.log(item);
}
// red
// green
// blue

for (let item of set.entries()) {
  console.log(item);
}
// ["red", "red"]
// ["green", "green"]
// ["blue", "blue"]

上面代码中,entries方法返回的遍历器,同时包括键名和键值,所以每次输出一个数组,它的两个成员完全相等。

Set 结构的实例默认可遍历,它的默认遍历器生成函数就是它的values方法。
Set.prototype[Symbol.iterator] === Set.prototype.values
// true
这就意味着,可以省略values方法,直接用for…of循环遍历Set

let set = new Set(['red', 'green', 'blue']);

for (let x of set) {
  console.log(x);
}
// red
// green
// blue

Set常用场景

Set最经典的应用就是数组排重:

let set = new Set([1, 2, 3, 3, 3, 4, 5]),
array = [...set];
console.log(array);

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

1、 Set与数组的转换

1.1、 Set转数组

使用扩展运算符可以很简单的将Set转成数组

let set = new Set([1, 2, 3, 3, 3, 4, 5]),
let array = [...set];
console.log(array); // [1,2,3,4,5]

该示例很好的说明了Set的一个重要的功能,数组排重,当然也很好的展示了,如何从Set转成数组的过程。
注意,这种转变是生成了一个新的数组对象原来的Set依然存在。

1.2、 数组转Set

如最初的构造示例:

let set = new Set([1,4,5,6,7]);

WeakSet:

由于 Set 类型存储对象引用的方式,它也可以被称为 strong Set 。对象存储在 Set 的一个实例中时,实际上相当于把对象存储在变量中。只要对于 Set 实例的引用仍然存在,所存储的对象就无法被垃圾回收机制回收,从而无法释放内存。

当 JS 代码在网页中运行,同时你想保持与 DOM 元素的联系,在该元素可能被其他脚本移除的情况下,你应当不希望自己的代码保留对该 DOM 元素的最后一个引用(这种情况被称为内存泄漏
为了缓解这个问题, ES6 也包含了 Weak Set ,该类型只允许存储对象弱引用,而不能存储基本类型的值。对象的弱引用在它自己成为该对象的唯一引用时,不会阻止垃圾回收。
WeakSet 里面的引用,都不计入垃圾回收机制,所以就不存在这个问题。因此,WeakSet 适合临时存放一组对象,以及存放跟对象绑定的信息。只要这些对象在外部消失,它在 WeakSet 里面的引用就会自动消失

WeakSet的构造:

Weak Set 使用 WeakSet 构造器来创建:

let set = new WeakSet(),
key = {};
// 将对象加入 set
set.add(key);
console.log(set.has(key)); // true
set.delete(key);
console.log(set.has(key)); // false

WeakSet的属性和方法:

基于WeakSet的弱引用特性,且里边的对象有可能随时消失的特性,es6规定WeakSet不可遍历,且没有size属性,WeakSet只有以下三个方法:
WeakSet.prototype.add(value):向 WeakSet 实例添加一个新成员。
WeakSet.prototype.delete(value):清除 WeakSet 实例的指定成员。
WeakSet.prototype.has(value):返回一个布尔值,表示某个值是否在 WeakSet 实例之中。

WeakSet的特性

  1. 对于 WeakSet 的实例,若调用add()方法时传入了非对象的参数,就会抛出错误(has()或delete()则会在传入了非对象的参数时返回false);
  2. Weak Set 不可迭代,因此不能被用在 for-of 循环中;
  3. Weak Set 无法暴露出任何迭代器; (例如 keys()与values() 方法,因此没有任何编程手段可用于判断 Weak Set 的内容);
  4. Weak Set 没有 forEach() 方法;
  5. Weak Set 没有 size 属性。

WeakSet之所以不可遍历是由于 WeakSet 内部有多少个成员,取决于垃圾回收机制有没有运行,运行前后很可能成员个数是不一样的,而垃圾回收机制何时运行是不可预测的,因此 ES6 规定 WeakSet 不可遍历。
WeakSet常用场景
Weak Set 看起来功能有限,而这对于正确管理内存而言是必要的。一般来说,若只想追踪对象的引用,应当使用 Weak Set 而不是正规 Set

脚本宝典总结

以上是脚本宝典为你收集整理的es6 Set和WeakSet全部内容,希望文章能够帮你解决es6 Set和WeakSet所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。