• Home
  • About
    • Damon photo

      Damon

      Make a daydream, with me.

    • Learn More
    • Twitter
    • Facebook
    • Instagram
    • Github
  • Posts
    • All Posts
    • All Tags

Symbol用起来

05 Jan 2019

Reading time ~1 minute

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具有更多的可能性,也更加友好啦。

https://juejin.im/post/5a0e65c1f265da430702d6b9



学习 Share Tweet +1