前言
对ES6中的 Symbol
、Reflect
、set
、WeakSet
、map
、WeakMap
Symbol
Symbol是ES6新定义的一直数据类型.他表示独一无二。
声明1
2
3
4{
let a = Symbol(),b = Symbol()
console.log(a === b) //false
}
Symbol.for机制有点类似于单例模式,首先在全局中搜索有没有以该参数作为名称的Symbol值,如果有,就返回这个Symbol值,否则就新建并返回一个以该字符串为名称的Symbol值。和直接的Symbol就点不同了1
2
3
4
5{
let a=Symbol.for('a');
let b=Symbol.for('a');
console.log(a===b); //true
}
symbol类型的数据使用一般的方法是查不出其属性的。需要使用Object.getOwnPropertySymbols()或者Reflect.ownKeys()1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24{
let a1=Symbol.for('abc');
let obj={
[a1]:'123',
'abc':345,
'c':456
};
console.log('obj',obj);} //obj { abc: 345, c: 456, [Symbol(abc)]: '123' }
for(let [key,value] of Object.entries(obj)){
console.log('let of',key,value);//let of abc 345
// let of c 456
}
Object.getOwnPropertySymbols(obj).forEach(function(item){
console.log(obj[item]); // 123
})
Reflect.ownKeys(obj).forEach(function(item){
console.log('ownkeys',item,obj[item]);
})
/*
ownkeys abc 345
ownkeys c 456
ownkeys Symbol(abc) 123
*/
Reflect对象
在上面提到的一个Reflect这个对象,多数Reflect方法原生的Object已经重新实现了.
为什么要使用Reflect
1 | 复制代码 |
在ES5中这样判断:name in obj ; 或者删除一个属性 :delete obj[name], 虽然这些很好用, 很简短, 很明确, 但是要使用的时候也要封装成一个类;
有了Reflect, 它帮你封装好了, Reflect.has(obj, name), Reflect.deleteProperty(obj, name);
Reflect.ownKeys()方法的使用:
Reflect.ownKeys, Object可没有ownKeys方法, Reflect.ownKeysz他的作用是返回对象的keys;1
2
3
4
5
6
7
8复制代码
console.log(Reflect.ownKeys({"a":0,"b":1,"c":2,"d":3})); //输出 :["a", "b", "c", "d"]
console.log(Reflect.ownKeys([])); // ["length"]
var sym = Symbol.for("comet");
var sym2 = Symbol.for("meteor");
var obj = {[sym]: 0, "str": 0, "773": 0, "0": 0,
[sym2]: 0, "-1": 0, "8": 0, "second str": 0};
Reflect.ownKeys(obj); //输出:/ [ "0", "8", "773", "str", "-1", "second str", Symbol(comet), Symbol(meteor) ]
Set
ES6提供了新的数据结构Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。
Set函数可以接受一个数组(或类似数组的对象)作为参数,用来初始化。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74{
let list = new Set();
list.add(5);
list.add(7);
console.log('size',list.size);//2
}
{
let arr = [1,2,3,4,5];
let list = new Set(arr);
console.log('size',list.size);//5
}
{
let list = new Set();
list.add(1);
list.add(2);
list.add(1);
console.log('list',list);//list Set { 1, 2 }
let arr=[1,2,3,1,'2'];//unique Set { 1, 2, 3, '2' }
let list2=new Set(arr);
console.log('unique',list2);
}
{
let arr=['add','delete','clear','has'];
let list=new Set(arr);
console.log('has',list.has('add'));//has true
console.log('delete',list.delete('add'),list);//delete true Set { 'delete', 'clear', 'has' }
list.clear();
console.log('list',list);//list Set {}
}
{
let arr=['add','delete','clear','has'];
let list=new Set(arr);
for(let key of list.keys()){
console.log('keys',key);
}
/*
keys add
keys delete
keys clear
keys has
*/
for(let value of list.values()){
console.log('value',value);
}
/*
value add
value delete
value clear
value has
*/
for(let [key,value] of list.entries()){
console.log('entries',key,value);
}
/*
entries add add
entries delete delete
entries clear clear
entries has has
*/
list.forEach(function(item){console.log(item);})
/*
add
delete
clear
has
*/
}
Set实现并集,交集,差集
1 | let set1 = new Set([1,2,3,4,5,6]); |
Map
1 | { |
WeakMap、WeakSet
他们对值的引用都是不计入垃圾回收机制的,所以名字里才会有一个weak,表示这个弱引用
下面以 WeakMap 为例,看看它是怎么解决内存泄漏的1
2
3
4const wm = new WeakMap();
const element = document.getElementById('example');
vm.set(element,'something');
vm.get(element);
先新建一个 Weakmap 实例。然后,将一个 DOM 节点作为键名存入该实例,并将一些附加信息作为键值,一起存放在 WeakMap 里面。这时,WeakMap 里面对element的引用就是弱引用,不会被计入垃圾回收机制。
也就是说,DOM 节点对象的引用计数是1,而不是2。这时,一旦消除对该节点的引用,它占用的内存就会被垃圾回收机制释放。Weakmap 保存的这个键值对,也会自动消失。
基本上,如果你要往对象上添加数据,又不想干扰垃圾回收机制,就可以使用 WeakMap