ES6的迁移之路---[4]

前言

对ES6中的 SymbolReflectsetWeakSetmapWeakMap

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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
复制代码
try {
Object.defineProperty(obj, name, desc);
// property defined successfully
} catch (e) {
// possible failure (and might accidentally catch the wrong exception)
}
//执行成功会返回obj, 以及其它原因导致的错误

if (Reflect.defineProperty(obj, name, desc)) {
// success
} else {
// failure
}
//只会返回false或者true来表示对象的属性是否设置上了

在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
2
3
4
5
6
7
8
9
10
11
12
let set1  = new Set([1,2,3,4,5,6]);
let set2 = new Set([4,5,6,7,8,9]);

//并集
let union = new Set([...set1,...set2]);
//[1,2,3,4,5,6,7,8,9]
//交集
let intersect = new Set([...set1].filter(x => b.has(s)));
//[4,5,6]
//差集
let intersect = new Set([...set1].filter(x => !b.has(s)));
//[1,2,3,4]

Map

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
let map = new Map();
let arr=['123'];

map.set(arr,456);

console.log('map',map,map.get(arr));//map Map { [ '123' ] => 456 } 456
}
{
let map = new Map([['a',123],['b',456]]);
console.log('map args',map);//map args Map { 'a' => 123, 'b' => 456 }
console.log('size',map.size);//size 2
console.log('delete',map.delete('a'),map);//delete true Map { 'b' => 456 }
console.log('clear',map.clear(),map);clear undefined Map {}
}

WeakMap、WeakSet

他们对值的引用都是不计入垃圾回收机制的,所以名字里才会有一个weak,表示这个弱引用
下面以 WeakMap 为例,看看它是怎么解决内存泄漏的

1
2
3
4
const 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

本文标题:ES6的迁移之路---[4]

文章作者:NoHomeMan

发布时间:2018年10月23日 - 15:10

最后更新:2018年10月23日 - 16:10

原始链接:http://nohomeman.github.io/ES6的迁移之路-4/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

-------------The End-------------