本篇文章给大家谈谈ES6中如何使用Set和WeakSet,以及es6中set用法的知识点,同时本文还将给你拓展ES6-WeakSet、ES6MapWeakMapSetWeakSet、ES6Set、We
本篇文章给大家谈谈ES6中如何使用Set和WeakSet,以及es6中set用法的知识点,同时本文还将给你拓展ES6 - WeakSet、ES6 Map WeakMap Set WeakSet、ES6 Set、WeakSet、ES6 Set和WeakSet等相关知识,希望对各位有所帮助,不要忘了收藏本站喔。
本文目录一览:- ES6中如何使用Set和WeakSet(es6中set用法)
- ES6 - WeakSet
- ES6 Map WeakMap Set WeakSet
- ES6 Set、WeakSet
- ES6 Set和WeakSet
ES6中如何使用Set和WeakSet(es6中set用法)
ES6中提供了两新数据结构-Set和WeakSet。Set是类似于数组,但是成员变量的值都是唯一的,没有重复的值。WeakSet也是不重复的值的集合,但是只能用来存放对象。
一、Set使用
(1)Set本身提供了一个构造函数,用来生成Set数据结构。
for(i of s){console.log(i)}
//2,1
(2)Set()函数可以接受一个数组,作为构造参数,用于做初始化。
注意:
向Set中加入值的时候不会发生类型转换,所以5和”5”是两个不同的值,Set内部判断两个值是否相等,使用的是 ===,这就意味着这两个对象总是不相等。唯一列外的是NaN本身(精确相等运算符认为NaN不等于自身)则,上面的代码表示,由于这两个空对象不是精确相等,所以是两个不同的值。
(3)Set的方法和属性
(3.1)Set的属性
Set.prototype.size:返回Set实例的成员数量。 Set.prototype.constructor:默认的构造@R_724_5301@。
(3.2)Set的操作啊函数
add(value):添加某个值,返回Set结构本身。 delete(value):删除某个值,返回一个布尔值,表示删除成功。 has(value):返回一个布尔值,表示参数是否为Set的成员。 clear():清除所有成员,没有返回值。
var set = new Set(); set.add(1).add(2).add(22).add(22); set.size//3
set.hae(22)//true set.has(4)//false set.delete(2)//true
(3.3)Set遍历操作
Set有四个遍历方法。可以用于遍历成员。 keys() :返回一个键名的遍历器 values() :返回一个值的遍历器 entries() :返回一个键值对的遍历器 forEach():使用回调函数遍历每个成员
注意:由于Set没有键名,只有值名,keys()和values()返回的结果是一样,
//所以,entries方法返回的遍历器同时包括键名和值,所以每次输出的是一个数组。其实成员都是完全一样的。
注意:Set默认的可遍历,其默认遍历器生成函数就是它的values方法。 这就意味着,可以省略values方法,直接用for…of遍历。
如果使用扩展运算符(…)内部使用for…of 循环,所以也可以用于Set结构。
(3.4)Set实现并集,交集,差集
let union = new Set([...set1,...set2]);
//[1,9]
//交集
let intersect = new Set([...set1].filter(x => b.has(s)));
//[4,6]
//差集
let intersect = new Set([...set1].filter(x => !b.has(s)));
//[1,4]
(3.5)Set实现forEach的使用
注意:
forEach方法的参数就是一个处理函数,该函数依次为(键值,键名)集合本身。另外,forEach方法还有第二个参数,表示绑定this的对象。二、WeakSet使用
WeakSet类似于Set,也是不重复的值的集合。但是它只能用于存储对象。而不能是其他类型的值。 WeakSet是一个个构造函数。可以接受数组和类似数组的对象作为参数。(实际上,任何具作为iterable接口的对象都可以作为WeakSet的参数)。该数组的所有成员都会自动成为WeakSet的实例对象的成员。 var a = new [[1,2],[3,4]]; var ws = new WeakSet(a);
添如一个数值和一个Symbol,结果同时报错。
WeakSet结构有以下的上方法 WeakSet.protoptype.add(value):向WeakSet实例添加一个新成员。 WeakSet.protoptype.delete(value):删除WeakSet实例指定成员。 WeakSet.protoptype.has(value):返回一个布尔值,表示某个值是否在WeakSet实例中。
WeakSet 不能遍历,是因为成员都是弱引用,随时可能消失,遍历不能保证成员的存在。可能刚刚遍历结束,成员就取不到了。WeakSet的一个用处是存储DOM节点,而不用担心这些节点从文档移除时,会引起内存的泄露。
ES6 - WeakSet
在我们进入在WeakSet的使用之前,我们先来看一个用Set来存储对象引用的例子:
let set = new Set();
let key = {};
set.add(key);
key = null;
console.log(set.size); // 1
console.log([...set][0]); // {}
以上代码,我们存储了一个对象的引用key,但是随后我们通过key = null
清楚了对象的引用,但是随后我们查看set.size依然得到1,且依然可以通过把set展开到数组取到原本已经被我们清除了引用的key。
之所以会出现这样的结果是因为,Set存储的是对象的强引用,虽然在代码的其他地方已经不存在对此变量的引用,但是javaScript的垃圾回收机制依然不会回收这段地址。这种情况,就会造成我们常说的内存泄漏。
而WeakSet就是为了解决上面的问题而存在的,相比Set,WeakSet存的是对象的弱引用。意思就是,如果在代码的其他地方已经不存在任何引用,那么WeakSet也不会再保留这个引用,这样就可以被垃圾回收了。
了解了以上WeakSet的存在背景,现在就来看一下WeakSet的一些特性和使用:
一:初始化WeakSet
一:通过new WeakSet()初始化
let weakSet = new WeakSet();
二:传入可迭代对象初始化
let key1 = {};
let key2= {};
let weakSet = new WeakSet([key1, key2]);
二:WeakSet的add(),delete(),has()方法
区别于Set,WeakSet只有三个方法可用,分别是
1: add() 添加一个元素
2: delete() 删除一个元素
3: has() 查询某个元素是否存在
它们的功能和用法与Set所对应的三个方法一致,只是在参数类型上有所限制,即:
以上三个方法都不能传入基本数据类型,只能传入对象类型。 我们先来看一下代码示例:
let key1 = {name: ''may''};
let key2= {name: ''april''};
let weakSet = new WeakSet([key1, key2]);
console.log(weakSet.has(key1)); // true
weakSet.delete(key2);
let key3 = {name: ''mike''};
let result = weakSet.add(key3);
console.log(result);
最后打印 console.log(result)
,我们得到结果:
WeakSet {{…}, {…}}
__proto__: WeakSet
[[Entries]]: Array(2)
0:
value: {name: "may"}
1:
value: {name: "mike"}
length: 2
可以看到因为调用delete(key2)
, 所以我们最后的结果里面没有了key2。
三:WeakSet与Set的区别
WeakSet与Set除了存储的分别是对象的弱引用和强引用之外,还有很多差别,下面我们就来总结一下WeakSet的特性:
1: WeakSet只能不能存储基本数据类型。这几意味着,在初始化和调用add()的时候,都只能传入对象类型的元素。
2: 如果给add()方法传入非对象类型,会抛出错误。给delete()和has()传入非对象类型参数,则总是返回false。
3: WeakSet不可迭代,所以所有迭代的场景都不能使用,例如for-of, 展开运算符等
4: WeakSet不暴露任何的迭代器,例如keys(),values(),这也是其不能被迭代的原因
5: WeakSet不支持forEach()方法
6: WeakSet不支持size属性
以上就是关于WeakSet的基本特性和功能。
ES6 Map WeakMap Set WeakSet
Map
js对象作为映射时主要的缺点是不能使用非字符串类型作为键,Map原则上来说可以使用任意数据类型作为键
let tMap = new Map();
let key1 = { x: 1 };
let key2 = { y: 2 };
// 赋值
tMap.set(key1, ''key1'');
tMap.set(key2, ''key2'');
// 取出所有值
let values = [ ...tMap.values() ];// [''key1'',''key2'']
// 在Map上使用entries()迭代
let items = [ ...tMap.entries() ];// [[{x:1}, ''key1''],[{y: 2}, ''key2'']]
// 判断是否有指定的键
tMap.has(key1); // true
// size属性和clear()方法
tMap.size // 2
// key1 = null 后tMap依然会存在{x:1}=''key1'',也就是说将key1原来的对象保存了下来,没有被GC掉
key1 = null
tMap.clear()
WeakMap
WeakMap是Map的变体,二者的行为特征基本上一致,区别在于内部的内存分配工作方式。
WeakMap没有values、entries、clear方法和size属性
WeakMap的键只接受对象,而且这些对象是被弱持有的,当key1 = null后 {x:1}这部分是可以被GC回收的,并且tMap中也将key1这一项删除
let tMap = new WeakMap();
let key1 = { x: 1 };
tMap.set(key1, ''key1'');
key1 = null // tMap中不存在key1这一项
Set
Set是一组值的集合,并且其中的值是唯一的
如果Set中添加的是对象类型数据,这个对象的接受者被赋值为null后,set中依然会存在赋值之前的值
let s = new Set();
// add 方法
s.add(''1'');
s.add(1);
// size属性
s.size // 2
/ 取出所有值
let values = [ ...s.values() ];// [''1'',1]
// 在Map上使用entries()迭代
let items = [ ...s.entries() ];// [[1, ''1''],[2, 1]]
// delete 方法
s.delete(''1'')
// clear 方法
s.clear()
// has方法
s.has(1) //true
let o = {name: 11};
s.add(o);
o = null; // s中依然会存在{name: 11}这一项数据
WeakSet
WeakSet 的值必须是对象
WeakSet 没有values、entries、clear方法和size属性
let wSet = new WeakSet();
let obj = {name: ''里斯''};
wSet.add(obj);
obj = null; // wSet中删除{name: ''里斯''}这一项数据
总结:对象作为Map的key或者作为Set的值时,这个对象的引用计数都是2,分别指向变量和Map的key或者Set的值,当把变量赋值为null时,只是将对象指向变量的引用清除掉,指向key或者值的引用依然保留。当对象作为WeakMap的key或者WeakSet的值时,这个对象在这两者之间的引用属于弱引用(弱引用不会屏蔽垃圾回收),可以理解为引用计数此时都是1,当把变量赋值为null时,对应的对象引用计数就为0,被GC。所以WeakMap和WeakSet的实例中都将销毁该项。
ES6 Set、WeakSet
Set、WeakSet
Set
Set
对象允许你存储任何类型的唯一值,无论是原始值或者是对象引用。
Set中的元素只会出现一次,即 Set 中的元素是唯一的。
NaN
和undefined
都可以被存储在Set 中, NaN
之间被视为相同的值(NaN被认为是相同的,尽管 NaN !== NaN)。
创建一个Set对象:
new Set([iterable])
iterable为可选参数,如果传递一个可迭代对象,它的所有元素将不重复地被添加到新的 Set中。
如果不指定此参数或其值为null
,则新的 Set为空。
属性:
size
返回Set对象中元素的个数。
var mySet = new Set();
mySet.add(1);
mySet.add(5);
mySet.add("some text")
mySet.size; // 3
方法:
Set.prototype.add(value)
在Set
对象尾部添加一个元素。返回该Set
对象。
Set.prototype.clear()
移除Set
对象内的所有元素。
Set.prototype.delete(value)
移除Set
中与这个值相等的元素,返回Set.prototype.has(value)
在这个操作前会返回的值(即如果该元素存在,返回true
,否则返回false
)。Set.prototype.has(value)
在此后会返回false
。
Set.prototype.entries()
返回一个新的迭代器对象,该对象包含Set
对象中的按插入顺序排列的所有元素的值的[value, value]
数组。为了使这个方法和Map
对象保持相似, 每个值的键和值相等。
Set.prototype.forEach(callbackFn[, thisArg])
按照插入顺序,为Set对象中的每一个值调用一次callBackFn。如果提供了thisArg
参数,回调中的this
会是这个参数。
Set.prototype.has(value)
返回一个布尔值,表示该值在Set
中存在与否。
Set.prototype.keys()
与values()
方法相同,返回一个新的迭代器对象,该对象包含Set
对象中的按插入顺序排列的所有元素的值。
Set.prototype.values()
返回一个新的迭代器对象,该对象包含Set
对象中的按插入顺序排列的所有元素的值。
Set.prototype[@@iterator]()
返回一个新的迭代器对象,该对象包含Set
对象中的按插入顺序排列的所有元素的值。
Set与Array
let myArray = ["value1", "value2", "value3"];
// 用Set构造器将Array转换为Set
let mySet = new Set(myArray);
mySet.has("value1"); // returns true
// 用...(展开运算符)将Set转换为Array
console.log([...mySet]); // 与myArray完全一致
实现数组去重
const numbers = [2,3,4,4,2,3,3,4,4,5,5,6,6,7,5,32,3,4,5]
console.log([...new Set(numbers)])
// [2, 3, 4, 5, 6, 7, 32]
WeakSet
WeakSet
对象是一些对象值的集合, 并且其中的每个对象值都只能出现一次。
new WeakSet([iterable]);
如果传入一个可迭代对象作为参数, 则该对象的所有迭代值都会被自动添加进生成的 WeakSet
对象中。null 被认为是 undefined。
WeakSet没有属性,只有三个实例方法。
方法:
add(value)
add()
方法在 WeakSet
对象的最后一个元素后添加新的对象。
ws.add(value);
value必须。 将对象添加进 WeakSet
集合中。
var ws = new WeakSet();
ws.add(window); // 添加 window 对象进 WeakSet 中
ws.has(window); // true
// Weakset 仅取得对象作为参数
ws.add(1);
// 结果为 "TypeError: Invalid value used in weak set" 在 Chrome 浏览器中
// 并且 "TypeError: 1 is not a non-null object" 在 Firefox 浏览器中
delete()
delete()
方法从 WeakSet 对象中
移除指定的元素.
ws.delete(value);
value为必须。从 WeakSet
对象中移除的对象。
var ws = new WeakSet();
var obj = {};
ws.add(window);
ws.delete(obj); // 返回 false。因为找不到要删除的obj
ws.delete(window); // 返回 true。成功地移除了元素
ws.has(window); // 返回 false。因为 WeakSet 中已经不存在 window 对象
has()
has()
方法根据 WeakSet
是否存在相应对象返回布尔值。
ws.has(value);
value必须。 测试 WeakSet
中是否存在该对象。
如果 WeakSet
对象中存在指定的元素,返回 true
;否则返回 false
。
与Set的区别
它和 Set
对象的区别有两点:
- 与
Set
相比,WeakSet
只能是对象的集合,而不能是任何类型的任意值。 WeakSet
持弱引用:集合中对象的引用为弱引用。 如果没有其他的对WeakSet
中对象的引用,那么这些对象会被当成垃圾回收掉。 这也意味着WeakSet中没有存储当前对象的列表。 正因为这样,WeakSet
是不可枚举的。
检测循环引用
递归调用自身的函数需要一种通过跟踪哪些对象已被处理,来应对循环数据结构的方法。
为此,WeakSet非常适合处理这种情况:
// 对 传入的subject对象 内部存储的所有内容执行回调
function execRecursively(fn, subject, _refs = null){
if(!_refs)
_refs = new WeakSet();
// 避免无限递归
if(_refs.has(subject))
return;
fn(subject);
if("object" === typeof subject){
_refs.add(subject);
for(let key in subject)
execRecursively(fn, subject[key], _refs);
}
}
const foo = {
foo: "Foo",
bar: {
bar: "Bar"
}
};
foo.bar.baz = foo; // 循环引用!
execRecursively(obj => console.log(obj), foo);
在此,在第一次运行时创建WeakSet
,并将其与每个后续函数调用一起传递(使用内部参数_refs)。 对象的数量或它们的遍历顺序无关紧要,因此,WeakSet比Set
更适合(和执行)跟踪对象引用,尤其是在涉及大量对象时。
ES6 Set和WeakSet




关于ES6中如何使用Set和WeakSet和es6中set用法的问题我们已经讲解完毕,感谢您的阅读,如果还想了解更多关于ES6 - WeakSet、ES6 Map WeakMap Set WeakSet、ES6 Set、WeakSet、ES6 Set和WeakSet等相关内容,可以在本站寻找。
本文标签: