有了上篇文章迭代器的基础, 这篇文章才意义.
生成器对象
function* gen() {
yield 1;
yield;
yield 3;
}
let g = gen();
生成器对象是由一个 generator function 返回的,并且它符合可迭代协议和迭代器协议。
g.next(); // {value: 1, done: false}
g.next(); // {value: undefined, done: false}
g.next(); // {value: 3, done: true}
通过打印,我们可以观察到一个生成器对象中包含三个函数,next() return() throw()
next()我们已经熟悉了
Generator.prototype.next()
返回一个由 yield
表达式生成的值。
return() 方法返回给定的值并结束生成器。
gen.return(value)
throw() 向生成器抛出一个错误。
generator函数中的this问题
// 正常函数
function F () {
this.a = 1
}
const f = new F()
// 调用构造函数F,返回实例对象f
// 将构造函数内部中的this指向这个实例对象
// 将构造函数中的原型对象赋值给实例对象的原型
// 执行构造函数中的代码
// 调用Generator函数会返回遍历器对象,而不是实例对象,因此无法获取到this指向的实例对象上的私有属性和方法。但是这个遍历器对象可以继承Generator函数的prototype原型对象上的属性和方法(公有属性和方法)。
function* g() {}
g.prototype.hello = function () {
return 'hi!';
};
let obj = g();
obj instanceof g // true
obj.hello() // 'hi!'
上面代码表明,Generator 函数g返回的遍历器obj,是g的实例,而且继承了g.prototype。但是,如果把g当作普通的构造函数,并不会生效,因为g返回的总是遍历器对象,而不是this对象。
应用generator 数组扁平化
function* flatten3(arr) {
let length = arr.length;
for (let i=0; i<length; i++) {
let item = arr[i];
if (Array.isArray(item)) {
yield* flatten3(item);
} else {
yield item;
}
}
}
let res = [];
for (let f of flatten3 (arr)) {
res.push(f);
}
console.log(res)
迭代方法
function flatten2(arr) {
const stack = [...arr];
const res = [];
while (stack.length) {
// 从栈里取出
const next = stack.pop();
if (Array.isArray(next)) {
// 把next扁平化,然后放入stack中
stack.push(...next);
} else {
res.push(next);
}
}
// reverse to restore input order
return res.reverse();
}
console.log(flatten2(arr))