基本用法
Set.prototype.add(value),在 Set 对象尾部添加一个元素
1 |
|
需要注意的是
1 |
|
数组作为构造参数传递进去时会被 set 解构,相当于把数组中的每一项 add 到 set 中,但使用 add 方法向 set 中添加数组时,整个数组是作为一个元素
Set.prototype.clear(),清除 Set 中的所有元素 Set.prototype.has(value),判断 value 是否存在于 Set 中 Set.prototype.delete(value) 删除 Set 中的某个值
1 |
|
遍历 Set 对象中的元素:forEach()、keys()、values()、entries()
forEach:
1 |
|
Set 结构的键名就是键值(两者是同一个值),因此第一个参数与第二个参数的值永远都是一样的
也可使用
for...of
keys():
1 |
|
values()、entries()跟 keys()大同小异,在此不作赘述
它的具体作用
-
去重
1
2const array = [...new Set([1, 1, "1", 2, 3, 2, 4, NaN, NaN])]; console.log(array); // [1, "1", 2, 3, 4, NaN]
Set 不会将元素进行类型转换,所以 1 和”1”是不相等的,并且 Set 中 NaN 是等于 NaN 的
降维去重并升序
1
2var arr = [ [1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14] ] ] ], 10]; Array.from(new Set(arr.flat(Infinity))).sort((a,b)=>{ return a-b})
-
速度快?
首先我们创建一个数组和一个 Set1
2
3
4
5
6
7
8
9
10
11
12
13
14
15let arr = [], set = new Set(), n = 1000000; console.time("Array"); for (let i = 0; i < n; i++) { arr.push(i); } console.timeEnd("Array"); console.time("Set"); for (let i = 0; i < n; i++) { set.add(i); } console.timeEnd("Set"); // Array: 29.285888671875ms // Set: 136.115966796875ms
好的,刚开始就啪啪打脸,接下来测试查找元素
1
2
3
4
5
6
7
8
9let result; console.time("Array"); result = arr.indexOf(123123) !== -1; console.timeEnd("Array"); console.time("Set"); result = set.has(123123); console.timeEnd("Set"); // Array: 0.174072265625ms // Set: 0.003662109375ms
查找元素相差几乎 50 倍
我们的结论是:Set 的 add()比 Array 的 push()要慢,但是查找元素 has()远远比 indexOf()快,各位看官看看就行。
WeakSet
它和Set
对象的区别有两点:
-
WeakSet
对象中只能存放对象引用, 不能存放值, 而Set
对象都可以. -
WeakSet
对象中存储的对象值都是被弱引用的, 如果没有其他的变量或属性引用这个对象值, 则这个对象值会被当成垃圾回收掉. 正因为这样,WeakSet
对象是无法被枚举的, 没有办法拿到它包含的所有元素. 在我刚看到弱引用时,我的想法是这样的:
1 |
|
然而实际输出:
,到底哪里有问题呢?
我们打印一下a
对象console.log(a)
,却发现输出{foo: "bar" }
查找资料后发现:
在 Javascript 是可以使用 delete 来手动删除变量,通过这样的方法让 GC 来回收内存,但在 JS 中并不是所有的对象都可以被删除的, kangex 在他的博文中对此作了详细说明: Understanding delete 在 JS 中通过 var\function 声明因含有 DontDelete,而不可被删除; 但是对象的属性、数组成员却是可以删除的;
因此如果我们要回收某个对象可以使用 Object 来封装一下。
1 |
|
然而
可以发现,我们已经成功删除了
test
中的content
,然而还是没有起作用,说好的弱引用呢??
原来,JavaScript 语言中,内存的回收并不是在执行 delete 操作符断开引用后即时触发的,而是根据运行环境的不同、在不同的运行环境下根据不同浏览器的回收机制而异的。比如在 Chrome 中,我们可以在控制台里点击 CollectGarbage 按钮来进行内存回收(不起作用?),关于在不同浏览器环境下手动进行内存回收的具体异同,可参考:如何手动触发 JavaScript 垃圾回收行为?(此链接过老,大部分方法已失效)
1 |
|