symbol 是 ES6 新增的一种基本数据类型,它和 number、 string、 boolean、 undefined 和 null 是同类型的,object 是引用类型。它用来表示独一无二的值,通过 Symbol 函数生成。
创建 symbol类型
symbol类型的值是通过Symbol构造函数创建的。
1 | const a = Symbol() |
Symbol的值是唯一
1 | let b = Symbol('key') |
用做对象属性的键
1 | let d = Symbol() |
声明对象的属性和类成员
1 | const f = Symbol() |
symbol值可以转为字符串和布尔类型值
1 | const i = Symbol('i') |
注意:symbol值不可以和其他类型的值进行运算
Symbol属性名的遍历
使用 Symbol 类型值作为属性名,这个属性不会被 for…in 遍历到,也不会被 Object.keys() Object.getOwnPropertyNames() JSON.stringify() 获取到:
1 | const name = Symbol('name') |
使用 Object.getOwnPropertySymbols() 方法获取对象的所有symbol类型的属性名。
1 | const name = Symbol('name') |
可以用 ES6 新提供的 Reflect 对象 的静态方法 Reflect.ownKeys,它可以返回所有类型的属性名,所以 Symbol 类型的也会返回。
1 | const name = Symbol('name') |
众所周知的Symbols
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)) // falseSymbol.isConcatSpreadable
布尔值,表示当在一个对象上调用Array.prototype.concat时,这个对象的数组元素是否可展开。1
2
3
4
5
6
7
8let 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' ]Symbol.iterator
方法,被for-of语句调用。返回对象的默认迭代器。1
2
3
4
5const 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 }Symbol.match
方法,被String.prototype.match调用。正则表达式用来匹配字符串。1
2
3
4
5
6
7
8
9
10
11
12const 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)) // trueSymbol.replace
方法,被String.prototype.replace调用。正则表达式用来替换字符串中匹配的子串。1
2
3
4
5
6
7
8
9
10
11class 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('老王'))) // 姓名:老王Symbol.search
方法,被String.prototype.search调用。正则表达式返回被匹配部分在字符串中的索引。Symbol.species
函数值,为一个构造函数。用来创建派生对象。Symbol.split
方法,被String.prototype.split调用。正则表达式来用分割字符串。Symbol.toPrimitive
方法,被ToPrimitive抽象操作调用。把对象转换为相应的原始值。Symbol.toStringTag
方法,被内置方法Object.prototype.toString调用。返回创建对象时默认的字符串描述。Symbol.unscopables
对象,它自己拥有的属性会被with作用域排除在外。