Set
Set 有序无重复集合,类似数组,但成员的值都是唯一的;
set 集合实现了 iterator 接口,所以可使用 「扩展运算符」 和 「for…of…」 进行遍历;
Set 属性和方法
属性和方法 | 描述 |
---|---|
size | 返回集合的元素个数 |
has() | 检测集合中是否包含某个元素,返回 boolean 值 |
add() | 增加一个新元素,返回当前集合 |
delete() | 删除元素,返回 boolean 值 |
clear() | 清空集合,返回 undefined |
keys() | 得到 Set 实例中的键作为一个可以遍历的对象,键和值相等,可以使用 .next().value 取值 |
values() | 得到 Set 实例中的值作为一个可以遍历的对象,可以使用 .next().value 取值 |
entries() | 得到 Set 实例中的键值作为一个可以遍历的对象,可以使用 .next().value 取值 |
基本使用
// 创建一个非空集合
let s1 = new Set([1, 2, 3, 1, 2, 3]);
// 返回集合的元素个数
console.log(s1.size); // 3
// 添加新元素
console.log(s1.add(4)); // Set(4) {1, 2, 3, 4}
// 删除元素
console.log(s1.delete(1)); // true
// 检测是否存在某个值
console.log(s1.has(2)); // true
// 使用扩展运算符
console.log([...s1]); // [2, 3, 4]
// 清空集合
console.log(s1.clear());
var set = new Set([1, 2, 3, 4]);
var values = set.values()
console.log(values.next().value); // 1
console.log(values.next().value); // 2
console.log(values.next().value); // 3
var set = new Set(['a', 'b', 'c'])
set.keys(); // SetIterator {"a", "b", "c"}
set.values(); // SetIterator {"a", "b", "c"}
set.entries(); // SetIterator {"a" => "a", "b" => "b", "c" => "c"}
for(var [key, value] of set.entries()) {
console.log(key, value);
}
// a, a
// b, b
// c, c
// Set 转 Array
// 1. 使用扩展运算符(...)可以将 Set 数据结构转化数组形式
var set = new Set([1, 2, 3, 4]);
console.log([...set]); // [1,2,3,4]
// 2. Array.from() 进行转化数组
var set = new Set([1, 2, 3, 4]);
console.log(Array.from(set)); // [1,2,3,4]
// 数组去重
console.log([...new Set([1, 2, 2, 3, 4])]); // [1,2,3,4]
console.log(Array.form(new Set([1, 2, 2, 3, 4]))); // [1,2,3,4]
手写 set
class MySet {
constructor(iterator = []) {
// 验证是否是可迭代的对象
if (typeof iterator[Symbol.iterator] !== "function") {
throw new TypeError(`你提供的${iterator}不是一个可迭代的对象`);
}
this._datas = [];
for (const item of iterator) {
this.add(item);
}
}
get size() {
return this._datas.length;
}
add(data) {
if (!this.has(data)) {
this._datas.push(data);
}
}
has(data) {
for (const item of this._datas) {
if (this.isEqual(data, item)) {
return true;
}
}
return false;
}
delete(data) {
for (let i = 0; i < this._datas.length; i++) {
const element = this._datas[i];
if (this.isEqual(element, data)) {
// 删除
this._datas.splice(i, 1);
return true;
}
}
return false;
}
clear() {
this._datas.length = 0;
}
*[Symbol.iterator]() {
for (const item of this._datas) {
yield item;
}
}
forEach(callback) {
for (const item of this._datas) {
callback(item, item, this);
}
}
/**
* 判断两个数据是否相等
* @param {*} data1
* @param {*} data2
*/
isEqual(data1, data2) {
if (data1 === 0 && data2 === 0) {
return true;
}
return Object.is(data1, data2);
}
}
WeakSet
WeakSet 存放的数据是一个弱引用类型,对元素的引用是弱引用,如果没有其他对象引用,GC 会对该对象进行回收;
不允许遍历,因为遍历的时候会有指针指向该对象,会对 GC 回收造成影响,所以存储带 weakSet 的数据是无法获取的,在现实开发中应用场景并不多;
方法
方法名 | 描述 |
---|---|
add | 向 WeakSet 实例中添加值 |
delete | 删除 WeakSet 实例中的指定值 |
has | 查找指定的值是否在 WeakSet 实例中 |
基本使用
var ws = new WeakSet();
var obj1 = {};
var obj2 = {};
ws.add(obj1);
ws.add(obj2);
ws.has(obj1); // true
ws.has(obj2); // true
ws.delete(obj1); // 从 set 中删除 obj1 对象
ws.has(obj1); // false, obj1 对象已经被删除了
ws.has(obj2); // true, obj2 依然存在
let obj = { name: "zhangsan", age: 18 };
let obj2 = obj;
const set = new WeakSet();
set.add(obj);
obj = null;
obj2 = null;
console.log(set); // WeakSet 中存储的对象被 GC 回收了
WeakSet VS Set
相同点
:WeakSet 和 Set 都是有序无重复的数据结构;
不同点
:
- WeakSet 只能是对象的集合,而不能是任何类型的任意值,Set 可以存储任何类型的值;
- WeakSet 中存储的对象值都是被弱引用的,如果没有其他的变量或属性引用这个对象值,则这个对象值会被当成垃圾回收掉;正因为这样 WeakSet 对象是无法被枚举的,没有办法拿到它包含的所有元素;
ES6+ 对象的扩展
上一篇