Symbol用起来
虽然es6中添加了Symbol, 但我在工作中几乎还是用不到的。所以想认真的学习一下,Symbol在实际生产生活中的用法。
阅读和学习了一些资料,对Symbol可以用到的场景有一下几种。
作为模拟私有属性
Symbol是唯一的,即使它的原始数据类型,即使创建了两个一模一样的Symbol,它们也是不一样的。
Symbol() === Symbol() // false
所以可以拿它作为对象的属性,并且不会发生重名覆盖的问题,是可以作为唯一的标识符的。但是Object.getOwnPropertySymbols可以获取到对象中所有的symbol,通过返回值还是可以调用和修改它的。
唯一但是也有例外
Symbol虽然提供了唯一性,但也提供了一种全局用法Symbol.for()。这个注册不仅是全局的,还是跨域的,也就是说iframe或者service worker中也可以获取到这个注册的Symbol并且可以共享。
另外也有Symbol.keyFor()方法可以获取到这个Symbol是不是全局的,需要注意的是,如果是全局的但没有描述的话,会返回’undefined’字符串,而如果是非全局的会返回一个undefined。
可以用作枚举类型
很多时候我们判断类型,会用一些字符串,但又解释不清楚,有的时候还会和其他的混在一起产生歧义。利用Symbol我们就可以做到使代码看起来清晰明了。
内置的Symbol属性(例举了某些)
Symbol.hasInstance
在ES6中改写了instanceof的实现,对象会内置一个Symbol.hasInstance的属性,该属性指向一个方法,它会判断该对象是否是传入对象的事例。
Symbol.iterator
通过改写这个属性,可以定义对象的迭代器,然后配合for..of使用
Symbol.match,Symbol.replace和Symbol的search
这几个比较有意思,允许自定义正则的规则。可以通过改写对象上的[Symbol.match](或者其他两个)属性来自定义规则
class MyMatcher {
constructor(value) {
this.value = value;
}
[Symbol.match](string) {
var index = string.indexOf(this.value);
if (index === -1) {
return null;
}
return [this.value];
}
}
var fooMatcher = 'foobar'.match(new MyMatcher('foo'));
var barMatcher = 'foobar'.match(new MyMatcher('bar'));
assert.deepEqual(fooMatcher, ['foo']);
assert.deepEqual(barMatcher, ['bar']);
Symbol.species
这个允许自己定义返回的类型。
Symbol.toPrimitive
这个属性提供了拆箱工作,当需要转为原始类型的时候会调用这个属性上的方法。这样你就可以愉快的自定义所转换的内容啦。
这里说的非常清楚:
This Symbol is the closest thing we have to overloading the Abstract Equality Operator (== for short). Basically, Symbol.toPrimitive is used when the JavaScript engine needs to convert your Object into a primitive value - for example if you do +object then JS will call objectSymbol.toPrimitive(‘number’), if you do ‘‘+object’ then JS will call objectSymbol.toPrimitive(‘string’), and if you do something like if(object) then it will call objectSymbol.toPrimitive(‘default’). Before this, we had valueOf and toString to juggle with - both of which were kind of gnarly and you could never get the behaviour you wanted from them.
const obj = {
[Symbol.toPrimitive]: (hint) => {
if (hint === 'string') {
return '123';
} else {
return 123;
}
}
}
Symbol.toStringTag
这个就简单了,就是Object.toString()方法的返回值啦!
class obj {
get [Symbol.toStringTag]() {
return 'obj';
}
}
console.log(new obj().toString());// [object obj]
Symbol其实非常好玩,特别是内置的这些属性,让js具有更多的可能性,也更加友好啦。