Symbol.hasInstance
判断一个实例是否属于某个类,实例通过instanceof判断, 类通过Symbol.hasInstance判断,可以通过修改类的Symbol.hasInstance函数修改逻辑
class Bar{}
class Baz extends Bar {}
let b = new Baz()
console.log(b instanceof Bar) // true
console.log(b instanceof Baz) // true
console.log(Bar[Symbol.hasInstance](b)) // true
console.log(Baz[Symbol.hasInstance](b)) // true
class Bar{}
class Baz extends Bar {
static [Symbol.hasInstance]() {
return false
}
}
let b = new Baz()
console.log(b instanceof Bar) // true
console.log(b instanceof Baz) // false
console.log(Bar[Symbol.hasInstance](b)) // true
console.log(Baz[Symbol.hasInstance](b)) // false
Symbol.iterator
根据 ECMAScript 规范,这个符号作为一个属性表示“一个方法,该方法返回对象默认的迭代器。
由 for-of 语句使用”。换句话说,这个符号表示实现迭代器 API 的函数。
for-of 循环这样的语言结构会利用这个函数执行迭代操作。循环时,它们会调用以 Symbol.iterator
为键的函数,并默认这个函数会返回一个实现迭代器 API 的对象。很多时候,返回的对象是实现该 API
的 Generator:
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() // 0 1 2 3 4
Symbol.asyncIterator
根据 ECMAScript 规范,这个符号作为一个属性表示“一个方法,该方法返回对象默认的 AsyncIterator。 由 for-await-of 语句使用”。换句话说,这个符号表示实现异步迭代器 API 的函数。
for-await-of 循环会利用这个函数执行异步迭代操作。循环时,它们会调用以 Symbol.asyncIterator
为键的函数,并期望这个函数会返回一个实现迭代器 API 的对象。很多时候,返回的对象是实现该 API
的 AsyncGenerator:
class Emitter {
constructor(max) {
this.max = max
this.asyncIdx = 0
}
async *[Symbol.asyncIterator]() {
while(this.asyncIdx < this.max) {
yield new Promise((resolve) => {
return resolve(this.asyncIdx++)
})
}
}
}
async function asyncCount() {
let emitter = new Emitter(5)
for await (const x of emitter) {
console.log(x)
}
}
asyncCount() // 0 1 2 3 4
Symbol.isConcatSpreadable
根据 ECMAScript 规范,这个符号作为一个属性表示“一个布尔值,如果是 true,则意味着对象应
该用 Array.prototype.concat()打平其数组元素”。ES6 中的 Array.prototype.concat()方法会
根据接收到的对象类型选择如何将一个类数组对象拼接成数组实例。覆盖 Symbol.isConcatSpreadable 的值可以修改这个行为。
数组对象默认情况下会被打平到已有的数组,false 或假值会导致整个对象被追加到数组末尾。类
数组对象默认情况下会被追加到数组末尾,true 或真值会导致这个类数组对象被打平到数组实例。其
他不是类数组对象的对象在 Symbol.isConcatSpreadable 被设置为 true 的情况下将被忽略。
const a = ["foo"]
const b = ["bar"]
a.concat(b) // ["foo", "bar"]
a[Symbol.isConcatSpreadable] = false
a.concat(b) // [Array(1), "bar"]
const a = { length: 1, 0: "baz" }
const b = ["foo"]
[].concat(a, b) // [{…}, "foo"]
a[Symbol.isConcatSpreadable] = true
[].concat(a, b) // ["baz", "foo"]
Symbol.match
根据 ECMAScript 规范,这个符号作为一个属性表示“一个正则表达式方法,该方法用正则表达式
去匹配字符串。由 String.prototype.match()方法使用”。String.prototype.match()方法会使
用以 Symbol.match 为键的函数来对正则表达式求值。正则表达式的原型上默认有这个函数的定义,
因此所有正则表达式实例默认是这个 String 方法的有效参数:
class FooMatcher {
static [Symbol.match](target) {
console.log(target)
return target.includes('foo');
}
}
"foobar".match(FooMatcher) // foobar true
FooMatcher[Symbol.match]("foobar") // foobar true
"bazbaz".match(FooMatcher) // foobar false
FooMatcher[Symbol.match]("bazbaz") // foobar false