写给自己看的ES6复习————Symbol

以前没做过笔记的内容复习

Symbol是ES6的一个新数据类型,第一眼看上去会感觉好像没什么卵用,

但是仔细想想是,会发现非常非常非常的实用。

Symbol特性

Symbol顾名思义,就是标志。

按照我个人的习惯,经常会出现用字符串作为case的值的情况,当然可以声明变量保存常量。

但是这样写起来就比较麻烦,Symbol就解决了我的这个问题。

Symbol的特性是每次调用Symbol,都会生成一个全新的独一无二的值,可以看下面这例子:

1
2
3
const a = Symbol('jerk');
const b = Symbol('jerk');
console.log(a === b); // false

可见每次调用Symbol产生的都是全新的值,由于字面看起来是一样的,所以可能会出现下面这种情况:

1
2
3
4
obj[a] = 'jerk';
obj[b] = 'butt';
console.log(obj)
{Symbol(jerk): "jerk", Symbol(jerk): "butt"}

看起来可能会有点迷惑,但是在不需要了解变量的字面量,只用到变量的时候是非常好用的,他有效的防止了字面量重复的问题。

方法

但是有的时候仅仅是需要一个独一无二的变量,并可以方便的用字面量访问,那怎么解决?

Symbol提供了Symbol.for()方法,用于创建字面量可复用的Symbol。
同时提供了Symbol.keyfor()方法用于访问字面量。

1
2
3
4
const a = Symbol.for('jerk');
const b = Symbol.for('jerk');
console.log(a === b); // true
Symbol.keyfor(a) // "jerk"

使用了Symbol.for声明的字面量是相等的,也就是

1
2
3
Symbol.for('jerk') === Symbol.for('jerk');
Symbol.for('jerk') !== Symbol('jerk');
Symbol('jerk') !== Symbol('jerk');

使用

在使用赋值Symbol的变量作为对象的属性名时,不能直接使用,需要通过括号进行赋值操作

1
2
3
4
const s = Symbol()
const a = {
[s]: 'symbolvalue'
}

同时访问的时候除非是用for方法生成的Symbol值,不然也无法直接通过Symbol字面量访问,需要通过变量名访问:

1
2
3
4
a[Symbol.for('jerk')] === 'forValue';
console.log(a[Symbol.for('jerk')]) // 'forValue';
a[Symbol('jerk')] = 'normalSymbol';
console[a[Symbol('jerk')]] // undefined;

无法通过for…in遍历

以上面为例,再给a赋值一个普通的属性

1
2
3
4
a.jerk = 'string';
for(key in a){
console.log(key); // jerk
}

可以看到Symbol值并没有被枚举出来,只枚举出了普通的属性名, 只能通过Object.getOwnPropertySymbols 或者Reflect.ownKeys(obj) 方法来枚举,好比我们一路用下来的

Object.getOwnPropertySymbols(obj) 可以只访问Symbol属性名,

而Reflect.ownKeys(obj) 会把对象的所有属性名都列出来,包括普通属性名和Symbol

1
2
3
4
5
const a = {};
a.sth = 'jerk';
a[Symbol('jerk')] = 'butt';
Reflect.ownKeys(a) // (2) ["sth", Symbol(jerk)]
Object.getOwnPropertySymbols(a) // [Symbol(jerk)]

可以看出Symbol非常适合用于作为枚举属性的值

或者作为需要隐藏,不被for in所枚举的静态方法。