概念
官话
迭代器模式是指提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。
人话
按照顺序,从集合中依次取出数据。
理解概念
内部迭代器
const each = ( ary, callback ) => {
for ( var i = 0, l = ary.length; i < l; i++ ){
// 把下标和元素当作参数传给 callback 函数
callback.call( ary[i], i, ary[ i ] );
}
};
each( [ 'a', 'b' , 'c' ], ( i, n ) => {
console.log( [ i, n ] );
});
外部迭代器
var o = {
0: 1,
1: 'a',
2: 'b',
3: 3,
4: 4,
length: 5,
};
// 定义外部迭代器,显式调用
var Interator = function(obj) {
var current = 0;
var next = function() {
current++;
}
var isDone = function() {
return current >= obj.length;
}
var getCurrent = function() {
return obj[current];
}
return {
next,
isDone,
getCurrent,
}
}
var interator = Interator(o)
while (interator.isDone() === false) {
// 依次输出 1, a, b, 3, 4
console.log(interator.getCurrent())
interator.next()
}
Iterator 接口的目的,就是为所有数据结构,提供了一种统一的访问机制。
原生语言支持
原生具备 Iterator 接口的数据结构如下:
- Array
- Map
- Set
- String
- TypedArray
- 函数的 arguments 对象
- NodeList 对象
let arr = ['a', 'b', 'c'];
let iter = arr[Symbol.iterator]();
iter.next() // { value: 'a', done: false }
iter.next() // { value: 'b', done: false }
iter.next() // { value: 'c', done: false }
iter.next() // { value: undefined, done: true }
iter.next() // { value: undefined, done: true }
iter.next() // { value: undefined, done: true }
使用场景
扩展运算符和解构赋值
// 例一
var str = 'hello';
[...str] // ['h','e','l','l','o']
// 例二
let arr = ['b', 'c'];
['a', ...arr, 'd']
// ['a', 'b', 'c', 'd'
// 例三
var [h,e] = [...str]
for of循环
// for...of 自动遍历拥有 Iterator 接口的数据结构
let arr = [1, 2, 3];
for (let item of arr) {
console.log(item);
}
// 输出:1 2 3
模式思考
配合生成器和yield语法实现异步控制
// *来声明这是一个生成器
function *foo(){
let x=10;
let y=20;
// yield是一个暂停点和一个表达式。yield的右边,是暂停时候的返回值(就是迭代器被调用next()后的返回值)。
let z = yield x+y;
return x + y +z;
}
//生成迭代器
let fooIterator = foo();
//第一次执行迭代器的next(),遇到 yield 返回,返回值是 yield 右侧的运行结果
console.log(fooIterator.next().value); // 30
//第二次执行迭代器的next(100), yield 及其右侧表达式的位置会替换为参数 100
console.log(fooIterator.next(100).value); // 130
function *fn(){
yield new Promise(res=> setTimeout(function(){res(1)},500));
yield new Promise(res=> setTimeout(function(){res(2)},500));
}
var gen = fn();
while(!gen.next().done){
Promise.resolve(gen.next().value)
}
和代理模式的比较
迭代器模式是为所有数据结构提供一种统一的访问机制。
代理模式是为隔离使用者和目标对象,仅通过代理使用目标对象的部分功能。
两者都是为了不暴露目标对象的内部表示。