定义Symbol

1
2
var sym = Symbol()
var sym1 = Symbol('foo')

Symbol('foo')并不会强制将字符串foo转化成symbol类型,他每次都会创建一个新的symbol类型
因此Symbol('foo') !== Symbol('foo')

如果想要创建一个Symbol包装器对象,可以使用Object()函数

1
2
3
4
var sym = Symbol('foo')
typeof sym // 'symbol
var symObj = Object(sym)
typeof symObj // 'object'

全局共享的Symbol
可以使用Symbol.for()Symbol.keyFor()方法从全局的symbol注册表设置和取得symbol

在对象中查找symbol属性
Object.getOwnPropertySymbols()查找一个给定对象的符号属性时返回一个symbol类型的数组,数组可能为空

属性

  1. Symbol.iterator 为每一个对象定义了默认的迭代器,可以被for...of循环使用
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
当需要对一个对象进行迭代时,它的`@@iterator`方法都会在不传参情况下被调用,返回的迭代器用于获取要迭代的值

一些内置类型拥有默认的迭代器行为
* `Array.prtotype[@@iterator]()`
* `TypedArray.prtotype[@@iterator]()`
* `String.prtotype[@@iterator]()`
* `Map.prtotype[@@iterator]()`
* `Set.prtotype[@@iterator]()`

**自定义迭代器**
~~~js
var myIterable = {}
myIterable[Symbol.iterator] = function* () {
yield 1;
yield 2;
yield 3;
}
[...myIterable] // [1,2,3]

for (var x of myIterable) {
console.log(x) / 1 -> 2 -> 3
}
~~~

如果一个迭代器没有返回一个迭代器对象,那么他是一个不合格的迭代器,在运行时将会抛出异常
  1. Symbol.asyncIterator 是一个用于访问对象的@@asyncIteratir方法的内建符号,一个异步可迭代对象必须要有Symbol.asyncIterator

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    const myAsyncIterable = new Object();
    myAsyncIterable[Symbol.asyncIterator] = async function*() {
    yield "hello";
    yield "async";
    yield "iteration!";
    };

    (async () => {
    for await (const x of myAsyncIterable) {
    console.log(x);
    // expected output:
    // "hello"
    // "async"
    // "iteration!"
    }
    })();
  2. Symbol.match指定了匹配的是正则表达式而不是字符串,String.prototype.match()方法会调用此函数

    1
    2
    3
    4
    const regexp = /foo/
    regexp[Symbol.match] = false
    console.log('foo'.startWith(regexp)) // true
    console.log('baz'.startWith(regexp)) // false
  3. Symbol.replace这个属性指定了当一个字符串替换所匹配字符串时调用的方法,String.prototype.replace()会调用此方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    class Replace {
    constructor(value) {
    this.value = value
    }
    [Symbol.replace](string) {
    return `s/${string}/${this.value}/g`
    }
    }
    console.log('foo'.replace(new Replace('bar'))) // s/foo/bar/g
  4. Symbol.search指定了一个搜索方法,这个方法接受用户输入的正则表达式,返回改正则表达式在字符串中匹配到的下标 String.prototype.search()会调用此方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    class caseInsensitiveSearch {
    constructor(value) {
    this.value = value.toLowerCase()
    }
    [Symbol.search](string) {
    return string.toLowerCase().indexOf(this.value)
    }
    }
    console.log('foobar'.search(new caseInsensitiveSearch('BaR'))); // 3
  5. Symbol.split指向一个正则表达式的索引处分割字符串的方法,这个方法通过String.prototype.split()调用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    /a/[Symbol.split]('aba', 3)

    var exp = {
    pat: 'in'
    [Symbol.split](str) {
    return str.split(this.pat)
    }
    }
    'dayinlove'.split(exp)
  6. Symbol.hasInstance 可以判断某对象是否为某构造器的实例,应此你们可以用它自定义instanceof操作符在某个类上的行为

    1
    2
    3
    4
    5
    6
    7
    class Array1 {
    static [Symbol.hasInstance](instance) {
    return Array.isArray(instance)
    }
    }

    console.log([] instanceof Array1) // true
  7. Symbol.isConcatSpreadable符号用于配置某对象作为Array.prototype.concat()方法的参数时是否展开数据元素

    1
    2
    3
    4
    5
    6
    7
    const a = ['a', 'b', 'c']
    const b = [1, 2, 3]
    let ab = a.concat(b) // ['a', 'b', 'c', 1, 2, 3]

    b[Symbol.isConcatSpreadable] = false
    ab = a.concat(b) // ['a', 'b', 'c', Array[1, 2, 3]]

  1. Symbol.toStringTag作为对象的属性键使用,对用的属性值应该为字符串类型,内置的Object.prototype.toString()方法会读取这个标签并把它包含在自己的返回值里面

    加上toStringTag属性,你的类也可以自定义类型标签

    1
    2
    3
    4
    5
    6
    class myClass {
    get [Symbol.toStringTag]() {
    return 'myClass'
    }
    }
    console.log(Object.prototype.toString.call(new myClass())) // '[object myClass]'
    1. Symbol.for()方法会根据给定的键key,来从运行时的symbol注册表中找到对应的symbol,如果找到了就返回,没有找到就新建一个symbol并加入到全局symbol的注册表中
    1
    2
    3
    4
    5
    6
    7
    8
    Symbol.for('foo')  // 全局注册 foo
    Symbol.for('foo') // 返回上一个全局注册的foo

    Symbol.for('foo') === Symbol.for('foo') // true
    Symbol('foo') === Symbol('foo') // false

    var sym = Symbol.for('mario')
    sym.toSstring() // 'Symbol(mario)'
    1. Symbol.keyFor() 用来获取全局symbol注册表中与某个symbol关联的键
    1
    2
    3
    4
    5
    6
    7
    8
    9
    // 创建一个全局 Symbol 
    var globalSym = Symbol.for("foo");
    Symbol.keyFor(globalSym); // "foo"

    var localSym = Symbol();
    Symbol.keyFor(localSym); // undefined,

    // 以下Symbol不是保存在全局Symbol注册表中
    Symbol.keyFor(Symbol.iterator) // undefined