20200419
Plan
- 你不知道的 js 下卷 - 第三章 代码组织
Notes
迭代器
接口
Iterator:
- 有一个 next()方法返回 IteratorResult
- (optional)支持 return() -- 停止迭代器并返回 IteratorResult 和 throw() 方法 -- 报错并返回 IteratorResult
IteratorResult:
- value: 当前迭代的值或最终返回的值
- done: bool 指示完成状态
Iterable
- '@@iterator' 方法,生成一个迭代器
next() 迭代
数组
var a = [1, 2, 3];
var it = a[Symbol.iterator](); // 生成迭代器
var it2 = a[Symbol.iterator](); // 这是一个全新的迭代器
it.next();
// {value: 1, done: false}
it.next();
// {value: 2, done: false}
it.next();
// {value: 3, done: false}
it.next(); // 必须再次调用next才能得到完成的信号
// {value: undefined, done: true}
字符串也可以迭代
var greeting = "hello world";
var it3 = greeting[Symbol.iterator]();
it3.next(); // {value: "h", done: false}
// ...
return 和 throw
迭代器循环 -- for...of
迭代器不一定是 iterable 的,只有 iterable 的对象才能被 for...of。
是迭代器成为 iterable
var it = {
[Symbol.iterator]() {
return this;
},
next() {
return; // ...
},
};
for...of 中,如果出现了 {done: true},那么迭代就不会再继续发生。等价于:
for(var res; res = it.next() && !res.done) {
// ...
}
所以当 next 返回最终值时,done 不能为 true。
自定义迭代器
无线斐波那契数列:
var fib = {
n1: 0,
n2: 0,
[Symbol.iterator]() {
return this;
},
next() {
if (this.n1 === 0) {
this.n1 = 1;
return {
value: 1,
done: false,
};
} else if (this.n2 === 0) {
this.n2 = 1;
return {
value: 1,
done: false,
};
}
[this.n1, this.n2] = [this.n2, this.n1 + this.n2];
return {
value: this.n2,
done: this.n2 > 1000,
};
},
return() {
console.log("something happened!");
return {
value: undefined,
done: true,
};
},
throw() {
console.log("something throwed!");
return {
value: undefined,
done: true,
};
},
};
for (var next of fib) {
if (next.value > 50) {
break; // 并不会响应 break?
}
console.log(next);
}
for (var a of [1, 2, 3]) {
if (a > 1) {
break; // 正确的停止
}
console.log(a);
}
这里不知道为什么,自己定义的迭代器不能被 break?
迭代器消耗
'...' spread 运算符可以消耗迭代器
function foo(a, b, c, d) {
//
}
foo(...[1, 2, 3, 4]); // 消耗