0%

【056】typescript:symbol类型

链接:Typescript中文官网,Symbols篇

symbolES6 新增的一种基本数据类型,它和 numberstringbooleanundefinednull 是同类型的,object 是引用类型。它用来表示独一无二的值,通过 Symbol 函数生成。

创建 symbol类型

symbol类型的值是通过Symbol构造函数创建的。

1
2
const a = Symbol()
console.log(typeof a) // symbol

Symbol的值是唯一

1
2
3
let b = Symbol('key')
let c = Symbol('key')
console.log(b === c) // false

用做对象属性的键

1
2
3
4
5
let d = Symbol()
let e = {
[d]: 'value'
}
console.log(e[d]) // value

声明对象的属性和类成员

1
2
3
4
5
6
7
8
const f = Symbol()
class G {
[f]() {
return 'value'
}
}
const h = new G()
console.log(h[f]()) // value

symbol值可以转为字符串和布尔类型值

1
2
3
const i = Symbol('i')
console.log(i.toString()) // Symbol(i)
console.log(Boolean(i)) // true

注意:symbol值不可以和其他类型的值进行运算

Symbol属性名的遍历

使用 Symbol 类型值作为属性名,这个属性不会被 for…in 遍历到,也不会被 Object.keys() Object.getOwnPropertyNames() JSON.stringify() 获取到:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const name = Symbol('name')
const person = {
[name]: '老王',
age: 30,
sex: '男'
}
let for_key = []
for (let key in person) {
for_key.push(key)
}
console.log(for_key) // [ 'age', 'sex' ]
console.log(Object.keys(person)) // [ 'age', 'sex' ]
console.log(Object.getOwnPropertyNames(person)) // [ 'age', 'sex' ]
console.log(JSON.stringify(person)) // {"age":30,"sex":"男"}

使用 Object.getOwnPropertySymbols() 方法获取对象的所有symbol类型的属性名。

1
2
3
4
5
6
7
const name = Symbol('name')
const person = {
[name]: '老王',
age: 30,
sex: '男'
}
console.log(Object.getOwnPropertySymbols(person)) // [ Symbol(name) ]

可以用 ES6 新提供的 Reflect 对象 的静态方法 Reflect.ownKeys,它可以返回所有类型的属性名,所以 Symbol 类型的也会返回。

1
2
3
4
5
6
7
const name = Symbol('name')
const person = {
[name]: '老王',
age: 30,
sex: '男'
}
console.log(Reflect.ownKeys(person)) // [ 'age', 'sex', Symbol(name) ]

众所周知的Symbols

  1. Symbol.hasInstance
    方法,会被instanceof运算符调用。构造器对象用来识别一个对象是否是其实例。

    1
    2
    3
    4
    5
    6
    7
    // 当其他对象使用 instanceof 判断是否为这个对象的实例时,会调用你定义的这个方法,参数是其他的这个对象
    const obj01 = {
    [Symbol.hasInstance](other: any) {
    console.log(other) // { a: 'a' }
    }
    }
    console.log({ a: 'a' } instanceof (obj01 as any)) // false
  2. Symbol.isConcatSpreadable
    布尔值,表示当在一个对象上调用Array.prototype.concat时,这个对象的数组元素是否可展开。

    1
    2
    3
    4
    5
    6
    7
    8
    let arr01 = [1, 2]
    console.log(arr01.concat([3, 4])) // [ 1, 2, 3, 4 ]
    let arr02 = ['a', 'b'] as any
    arr02[Symbol.isConcatSpreadable] = false
    console.log(arr02.concat(['c', 'd'])) // [ [ 'a', 'b', [Symbol(Symbol.isConcatSpreadable)]: false ], 'c', 'd' ]
    // 当数组arr02的 Symbol.isConcatSpreadable 设为 true 时,这个数组在数组的 concat 方法中不会被扁平化
    arr02[Symbol.isConcatSpreadable] = true
    console.log(arr02.concat(['e', 'f'])) // [ 'a', 'b', 'e', 'f' ]
  3. Symbol.iterator
    方法,被for-of语句调用。返回对象的默认迭代器。

    1
    2
    3
    4
    5
    const arr = [1, 2]
    const iterator = arr[Symbol.iterator]()
    console.log(iterator.next()) // { value: 1, done: false }
    console.log(iterator.next()) // { value: 2, done: false }
    console.log(iterator.next()) // { value: undefined, done: true }
  4. Symbol.match
    方法,被String.prototype.match调用。正则表达式用来匹配字符串。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    const obj = {
    [Symbol.match](val: any) {
    return val.length
    }
    }
    console.log('abcdefg'.match(obj)) // 7

    // 正则表达式用来匹配字符串
    const str: any = /abcdefg/
    str[Symbol.match] = false
    console.log('/abc/'.startsWith(str)) // false
    console.log('/abcdefg/'.endsWith(str)) // true
  5. Symbol.replace
    方法,被String.prototype.replace调用。正则表达式用来替换字符串中匹配的子串。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class obj02 {
    value: string
    constructor(value: any) {
    this.value = value
    }
    [Symbol.replace](str: any) {
    return `${str}:${this.value}`
    }
    }
    const n: any = '姓名'
    console.log(n.replace(new obj02('老王'))) // 姓名:老王
  6. Symbol.search
    方法,被String.prototype.search调用。正则表达式返回被匹配部分在字符串中的索引。

  7. Symbol.species
    函数值,为一个构造函数。用来创建派生对象。

  8. Symbol.split
    方法,被String.prototype.split调用。正则表达式来用分割字符串。

  9. Symbol.toPrimitive
    方法,被ToPrimitive抽象操作调用。把对象转换为相应的原始值。

  10. Symbol.toStringTag
    方法,被内置方法Object.prototype.toString调用。返回创建对象时默认的字符串描述。

  11. Symbol.unscopables
    对象,它自己拥有的属性会被with作用域排除在外。