创建Symbol

let a = Symbol()
let b = Symbol('b')

let person = {
    [a]: 'one',
    [b]: 'oneday',
}

console.log(person[a]) // one
console.log(a) // Symbol()
console.log(person[b]) // oneday
console.log(b) // Symbol(b)

可以使用typeof操作符来获得变量的属性:

typeof a // "symbol"

如果想在不同的对象中共享一个Symbol,可以使用Symbol.for()

let a = Symbol.for('a')
let b = Symbol.for('a')

let person = {
    [a]: 'one',
}

console.log(a === b) // true
console.log(person[a]) // a
console.log(person[b]) // a

Symbol.for()方法首先在全局Symbol注册表中搜索键为'one'的Symbol是否存在,如果存在,直接返回已有的Symbol值,否则会创建一个新的Symbol并在Symbol的注册表中注册,然后返回该新创建的Symbol。如上,a和b可以互换。

Symbol.keyFor()方法在Symbol全局注册表中检索与Symbol有关的键:

console.log(Symbol.keyFor(a)) // one
console.log(Symbol.keyFor(b)) // one

let c = Symbol('a')
console.log(Symbol.keyFor(c)) // undefined

不能将Symbol强制转换为字符串和数字类型。

Object.keys()方法和Object.getOwnPropertyNames()方法可以检索对象中所有的属性名:前一个返回所有可枚举的属性名;后一个方法不考虑属性的可枚举性一律返回。而想要枚举Symbol属性则需要一个新的方法:Object.getOwnPropertySymbols(),会返回一个包含对象所有Symbol属性的数组:

let a = Symbol('a')
let b = Symbol('b')
let c = Symbol('c')

let person = {
    [a]: 'one',
    [b]: 'day',
    [c]: 'oneday'
}

let arr = Object.getOwnPropertySymbols(person)
console.log(arr) // (3) [Symbol(a), Symbol(b), Symbol(c)] 0: Symbol(a) 1: Symbol(b) 2: Symbol(c)

Symbol.hasInstance

用于确定对象是否为函数的实例。不可写、不可配置并且不可枚举。

arr instanceof Array相当于Array[Symbol.hasInstance](obj)

可以通过Symbol.hasInstance设置为false手动将一个函数设置为“无实例”的(其实是实例,只是返回了false)。

function MyObject() {}

Object.defineProperty(MyObject, Symbol.hasInstance, {
    value: function(v) {
        return false
    }
})

let obj = new MyObject()
console.log(obj instanceof MyObject) // false

Symbol.isConcatSpreadable

一个布尔值,如果该属性为true,则表示对象有length属性和数字键,故它的数值型属性值应该被独立添加到concat()调用的结果中。是一个可选属性。

let collection = {
    0: 'hello',
    1: 'world',
    length: 2,
    [Symbol.isConcatSpreadable]: true
}

let message = ['hi']

let a = message.concat(collection)
console.log(a) // (3) ["hi", "hello", "world"]

如果不设置该属性或设置为false,则结果为(2) ["hi", {…}]

Symbol.matchSymbol.replaceSymbol.searchSymbol.split

都会在调用String.prototype.xxx函数时被调用。

  • Symbol.match:接受一个字符串类型的参数,如果匹配成功则返回匹配元素的数组,否则返回null;
  • Symbol.replace:接受一个字符串类型的参数和一个替换用的字符串,最终依然返回一个字符串;
  • Symbol.search:接受一个字符串参数,如果匹配到内容,则返回数字类型的索引位置,否则返回-1;
  • Symbol.split:接受一个字符串参数,根据匹配内容将字符串分解,并返回一个包含分解后片段的数组。

    Symbol.iterator

    一个返回迭代器的方法。

    Symbol.species

    一个用于创建派生类的构造函数。

    Symbol.toPrimitive

    返回对象原始值。

JavaScript中,执行特定操作时,经常会尝试将对象转换为相应的原始值,例如比较一个字符串和一个对象,如果使用双等号(==)运算符,对象会在比较操作前被转换为一个原始值。

对于大多数标准对象,数字模式有以下特性,根据优先级的顺序排列如下:

  • 调用valueOf()方法,如果结果为原始值,则返回;
  • 否则,调用toString()方法,如果结果为原始值,则返回;
  • 如果再无可选值,则抛出错误。

对于大多数标准对象,字符串模式有以下特性,根据优先级的顺序排列如下:

  • 调用toString()方法,如果结果为原始值,则返回;
  • 否则,调用valueOf()方法,如果结果为原始值,则返回;
  • 如果再无可选值,则抛出错误。

如果自定义Symbol.toPrimitive方法,则可以覆盖这些默认的强制转换特性。

function Temperature(degree) {
    this.degree = degree
}

Temperature.prototype[Symbol.toPrimitive] = function(hint) {
    switch(hint) {
        case 'string': 
            return this.degree + '\u00b0'
        case 'number':
            return this.degree
        case 'default':
            return this.degree + ' degrees'
    }
}

var freezing = new Temperature(27)

console.log(freezing + '!') // 27 degrees!
console.log(freezing / 2) // 13.5
console.log(String(freezing)) // 27°

hint在这里作为类型提示参数,类型提示参数的值只有三种选择:'number'、'string'或'default'。传递这些参数时,Symbol.toPrimitive返回的分别是数字、字符串或无类型的值。所以上例中,+触发default模式,/运算符触发数字模式,String触发字符串模式。

Symbol.toStringTag

可以改变调用Object.prototype.toString()返回的身份标识。

经常会遇到问怎么判断一个数组是不是一个数组的问题,因为typeof []返回object,所以就有了这样的方法:

Object.prototype.toString.call([]) // [object Array]

但是[Symbol.toStringTag]可以改变这个返回值,如下:

Array.prototype[Symbol.toStringTag] = 'Oneday'
Object.prototype.toString.call([]) // [object Oneday]

所以不要用这个特性去更改内建对象。

Symbol.unscopables

通常用于Array.prototype,以在with语句中表示出不创建with绑定的属性名。Symbol.unscopables是以对象的形式出现的,它的键是在with语句中要忽视的标识符(函数名),其对应的值必须是true。例如:

Array.prototype[Symbol.unscopables] = Object.assign(Object.create(null), {
    copyWithin: true,
    entries: true,
    fill: true,
    find: true,
    findIndex: true,
    keys: true,
    values: true
})

results matching ""

    No results matching ""