目录
前言
本篇笔记 JS 语言基础 第三篇。
主要内容有:
- ES6 新增简单数据类型 Symbol 的属性;
随书附录:随书下载中的附录A中介绍了关于 异步迭代器 和 for-await-of 循环的细节
1、Symbol.asyncIterator
根据 ECMAScript 规范,这个符号作为一个属性表示:一个方法,该方法返回对象默认的 AsyncIterator,由 for-await-of 语句使用。即,这个符号表示实现异步迭代器 API 的函数。
class Foo {
async *[Symbol.asyncIterator]() {}
}
let f = new Foo();
console.log(f[Symbol.asyncIterator]()); // AsyncGenerator {<suspended>}
技术上,这个由 Symbol.asyncIterator 函数生成的对象应该通过其 next() 方法陆续返回 Promise 实例。可以通过显式地调用 next() 方法返回,也可以隐式地通过异步生成器函数返回:
class Emit {
constructor(max) {
this.max = max;
this.asyncIdx = 0;
}
async *[Symbol.asyncIterator]() {
while(this.asyncIdx < this.max) {
yield new Promise((resolve) => resolve(this.asyncIdx++));
}
}
}
async function asyncCount() {
let emit = new Emit(5);
for await(const x of emit) {
console.log(x);
}
}
asyncCount();
// 0
// 1
// 2
// 3
// 4
代码中创建了一个简单的 Emit 类,该类包含一个同步生成器函数,该函数会产生一个同步迭代器,同步迭代器输出 0~4。
2、Symbol.hasInstance
这个符号作为一个属性表示:一个方法,该方法决定一个构造器对象是否认可一个对象是它的实例,由 instanceof 操作符使用。instanceof 操作符可以用来确定一个对象实例的原型链上是否有原型。
function Foo() {}
let f = new Foo();
console.log(f instanceof Foo); // true
class Bar {}
let b = new Bar();
console.log(b instanceof Bar); // true
使用 Symbol.hasInstance 为键的函数会执行同样的操作,只是将操作数对调一下即可:
function Foo() {}
let f = new Foo();
console.log(Foo[Symbol.hasInstance](f)); // true
class Bar {}
let b = new Bar();
console.log(Bar[Symbol.hasInstance](b)); // true
这个属性定义在 Function 的原型上,因此默认在所有函数和类上都可以调用,同时,由于 instanceof 操作符会在原型链上寻找这个属性的定义,因此我们可以在继承的类上面通过静态方法重新定义这个函数:
class Bar {}
class Baz extends Bar { // Baz 继承 Bar
static [Symbol.hasInstance]() {
return false;
}
}
let b = new Baz();
console.log(Bar[Symbol.hasInstance](b)); // true
console.log(b instanceof Bar); // true
console.log(Baz[Symbol.hasInstance](b)); // false
console.log(b instanceof Baz); // false
3、Symbol.isConcatSpreadable
这个符号作为一个属性表示:一个布尔值,如果是 true ,则意味着对象应该用 Array.prototype.concat() 打平其数组元素。
ES6 中的 Array.prototype.concat() 方法会根据接收到的对象类型选择如何将一个类数组对象拼接成数组实例。覆盖 Sym