Symbol
-
用途:确保对象属性使用唯一标识符,不会发生属性命名冲突
-
Symbol()
创建,参数为描述 -
不能使用
new
-
不能与其他类型运算
- 只能转为字符串或布尔值
-
在对象内不会自动转换为字符串
-
不能使用
.
,只能用[]
Symbol.for
-
Symbol.for()
与Symbol()
这两种写法,都会生成新的Symbol
对象 -
Symbol.for()
:会保存在全局注册表中,如果描述相同则不会生成新的,而是重复调用没有参数则描述为
undefined
const s1=Symbol.for('1') const s2=Symbol.for('1') console.log(s1===s2);//true const s3=Symbol('1') console.log(s1===s3);//false
-
Symbol.keyFor()
可以查询全局注册表,参数为全局注册过的Symbol
对象let s = Symbol.for('foo'); console.log(Symbol.keyFor(s)); // foo
方法
Reflect.ownKeys(obj)
:返回自身所有属性(包括Symbol
属性)Object.getOwnPropertySymbols(obj)
:返回自身所有Symbol
属性Object.getOwnPropertyDescriptors()
:返回自身所有描述对象(包括Symbol
属性)Object.assign
:对象合并(识别symbol
)
内置Symbol属性
Symbol.hasInstance()
class Baz {
static [Symbol.hasInstance](obj) {}
}
- 在使用
instanceof
运算符时调用
Symbol.isConcatSpreadable
arrayLikeObject[Symbol.isConcatSpreadable] = true;
- 值为布尔值,在
Array.prototype.concat()
时,用于判断是否展开(一层) - 数组的默认行为是可以展开
Symbol.iterator
class Emitter {
constructor(max) {
this.max = max;
this.idx = 0;
}
*[Symbol.iterator]() {
while(this.idx < this.max) {
yield this.idx++;
}
}
}
function count() {
let emitter = new Emitter(5);
for (const x of emitter) {
console.log(x);
}
}
count();
- 对象进行
for...of
循环时调用 - 函数应该返回遍历器
Symbol.asynIterator
class Emitter {
constructor(max) {
this.max = max;
this.idx = 0;
}
//生成器在类中的写法
*[Symbol.iterator]() {
while (this.idx < this.max) {
yield this.idx++;
}
}
}
async function asyncCount() {
let emitter = new Emitter(5);
for await(const x of emitter) {
console.log(x);
}
}
asyncCount();
// 0
// 1
// 2
// 3
// 4
- 对象进行
for await...of
循环时调用
Symbol.match
class FooMatcher {
static [Symbol.match](str) {}
}
- 在使用
String.prototype.match()
时调用
Symbol.replace
class FooReplacer {
static [Symbol.replace](target, replacement) {}
}
- 在使用
String.prototype.replace()
时调用
Symbol.search
class FooSearcher {
static [Symbol.search](target) {}
}
- 在使用
String.prototype.search()
时调用
Symbol.species(常用)
class MyArray extends Array {
static get [Symbol.species]() {
console.log('创建了衍生对象');
}
}
const a = new MyArray(1, 2, 3);
const b = a.map(x => x); //创建了衍生对象
const c = a.filter(x => x > 1); //创建了衍生对象
- 创建衍生对象时调用
- 注意要采用
get
取值器
Symbol.split
class FooSplitter {
static [Symbol.split](target) {}
}
- 在使用
String.prototype.split()
时调用
Symbol.toPrimitive
class Bar {
constructor() {
this[Symbol.toPrimitive] = function (hint) {
switch (hint) {
case 'number':
return 3;
case 'string':
return 'string bar';
case 'default':
default:
return 'default bar';
}
}
}
}
let bar = new Bar();
console.log(3 + bar); // "3default bar"
console.log(3 - bar); // 0
console.log(String(bar)); // "string bar"
- 对象被转为原始类型时调用
- 返回该对象对应的原始类型值
- 接受一个字符串参数,表示当前运算的模式:
- Number:需要转成数值
- String:需要转成字符串
- Default:可以转成数值,也可以转成字符串
Symbol.toStringTag
class Collection {
get [Symbol.toStringTag]() {
return 'xxx';
}
}
let x = new Collection();
Object.prototype.toString.call(x) // "[object xxx]"
- 在
Object.prototype.toString()
时调用 - 返回值可以用来定制数据类型
[object 定制]