迭代模式:
提供一种方法可以顺序获得聚合对象中的各个元素,是一种最简单也是最常见的一种设计模式。它可以让用户透过特定的接口巡访集合中的每一个元素而不用了解底层的实现
迭代器简介:
依照与迭代模式的思想而实现,分为内部迭代器和外部迭代器
内部迭代器:
本身是函数,该函数内部定义好迭代规则,完全接手整个迭代过程,外部只需要一次初始化调用
Array.prototype.forEach
外部迭代器:
本身是函数,执行返回迭代对象,迭代下一个元素必须显示调用,调用复杂度增加,但灵活性增强
function outerIterator() {} 外部迭代器
迭代器目的
从迭代模式思想中可以看出,就是要标准化 迭代操作
举个例子
服务端提供数组数据给前端,前端for循环遍历,但由于业务变化,使得数据结构发生变化,返回对象或者set map,导致前端遍历代码大量重写
解决方案
ES6引入Iterator,部署在NodeList Arguments Array Set Map String等数据的Symbol.iterator属性上
console.log(Symbol('Symbol.iterator'), Symbol.iterator)
使得这些数据是iterable可迭代的,能进行for…of… Array.from()等操作
Iterator
概念:
遍历器(Iterator)就是这样一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作(即依次处理该数据结构的所有成员),也就是说主要是给for…of…进行消费
iterator实现规则:
next value done
根据规则:手动模拟一个简单demo
let arr = [1, 3, 5]
function OuterIterator(o) {
let curIndex = 0
let next = () => {
return {
value: o[curIndex],
done: o.length === ++curIndex
}
}
return { next }
}
let oIt = OuterIterator(arr)
Symbol
概念: 一种新的数据结构
出现原因: ES5 的对象属性名都是字符串,这容易造成属性名的冲突。比如,你使用了一个他人提供的对象,但又想为这个对象添加新的方法(mixin 模式),新方法的名字就有可能与现有方法产生冲突。如果有一种机制,保证每个属性的名字都是独一无二的就好了,这样就从根本上防止属性名的冲突。
let oS = Symbol('abc')
console.log(oS)
// 这个例子说明了Symbol如果传入的是一个对象,那么会调用Object.prototype.toString()的方法,下边是进行了重写
let oS1 = Symbol({
value: 'chen',
toString: function() {
return 'i love study'
}
})
console.log(oS1)
特点:
唯一,可以作为对象的属性,有静态属性Symbol.iterator(对应的是一个遍历器生成函数)
这个demo体现了唯一性
let oS = Symbol('abc')
let oS1 = Symbol('abc')
// 唯一
console.log(oS1 == oS) // false
根据以上的知识,那么我们可以尝试在对象上实现for…of遍历功能
var obj = {
0: 'chen',
1: 'chongxuan',
length: 2,
// 至于属性名Symbol.iterator,它是一个表达式,返回Symbol对象的iterator属性,这是一个预定义好的、类型为 Symbol 的特殊值,所以要放在方括号内
[Symbol.iterator]: function() {
let curIndex = 0
let next = () => {
return {
value: this[curIndex],
done: this.length == curIndex++
}
}
return { next }
}
}
console.log([...obj])
for (let prop of obj) {
console.log(prop)
}