迭代模式
提供一种方法, 可以顺序获得聚合对象中的各个元素。可以让用户通过特定的接口遍历集合中的每一个元素, 而不必了解底层原理。
for
循环, 数组的forEach
方法。 都是迭代器, 属于内部迭代器(用户无需关心如何实现,只是调用接口就好了,迭代器会完全接手迭代过程)。
外部迭代器: 每一次迭代用户都是可控的。
例如一个iterator
,用户想遍历下一个元素, 就调用一次next()
函数, 这个函数返回一个对象,里面是当前正在遍历的值, 以及是否完成了整个迭代过程的标志。
let arr = [1,2,3,4,5,6]
let I = myIterator(arr)
I.next() // { value: 1, done: false} ..... {value: 6, done: true}
类似这样的实现, 就是外部迭代器。所以可以尝试实现一下。
function OuterIntertor (arr){
let curIndex = 0
let next = () => {
return {
value: arr[curIndex],
done: arr.length === ++ curIndex
}
}
return {
next
}
}
当然这是一个简单的示例, 如果继续往下遍历, 由于js的机制虽然不会报错, 但是也是可以没有意义地无限的进行下去。
ES6
引入了iterator
将其部署在NodeList
, arguments
, Array
,Set
, Map
, String
上,在他们的构造函数上可以找到Symbol.iterator
. 使得这些数据结构 iterable
的 。 能使用 for
, for of
, for in
, ...
, Array.from
的操作。
Symbol
Symbol
是js
中的第七种数据类型。它就是一种新的数据类型, 不属于之前任何一种。
Symbol
的值是唯一的,尽管脸两个长得一样的Symbol
, 他们仍然不相等。
let s1 = Symbol('abc');
let s2 = Symbol('abc');
let obj = {
[s1]: 'vey1',
[s2]: 'vey2'
}
console.log(obj)
// {Symbol(abc): "vey1", Symbol(abc): "vey2"}
两个长得一样的Symbol, 代表了不同的值。
部署 Iterator 接口
let obj = {
0: 'c',
1: 'b',
2: 'a',
length: 3
}
console.log([ ...obj ])
// Uncaught TypeError: obj is not iterable
因为没有iterator接口, 所以不是可以迭代的。
按照ES6的规范去实现它(value, done, next)
。
var a = {
0: 'c',
1: 'b',
2: 'a',
length: 3,
[Symbol.iterator]: function(){
let curIndex = 0;
let next = () => {
return {
value: this[curIndex],
done: this.length === curIndex ++
}
}
return {
next
}
}
}
[...a] // ["c", "b", "a"]