从JavaScript学习设计模式(Iterator)

  ES6增加了Map,Set数据结构而且还实现了迭代器机制(Iterator),这是多么令人兴奋的事情。

迭代器(Iterator)模式,又叫做游标(Cursor)模式。GOF给出的定义为:提供一种方法访问一个容器(container)对象中各个元素,而又不需暴露该对象的内部细节。 从定义可见,迭代器模式是为容器而生。很明显,对容器对象的访问必然涉及到遍历算法。你可以一股脑的将遍历方法塞到容器对象中去;或者根本不去提供什么遍历算法,让使用容器的人自己去实现去吧。这两种情况好像都能够解决问题。(取自百度百科,发现百度的名词解释比维基棒 :P )


即Iterator是为了遍历容器(set , map , array,object)而提供的接口


下面我会从几个方面来阐述JavaScript的迭代器:
0x00 Iterator实现原理及使用
0x01 对JavaScript的循环方法进行汇总


0x00 Iterator原理及使用姿势

实际上遍历的原理大家都能想得到。

抽象数据类型(Abstract Data Type ADT)是一个数据模型以及包含对数据的操作,定义并实现了抽象数据模型就可以像使用基本数据类型那样。

数据结构是实现抽象数据类型的算法。

首先创建我们需要一个类似指针☞的对象(下面称为指针对象),记下当前抽象数据类型起点(数组,对象等可遍历数据类型,阮老师这里写的是数据结构,个人认为ADT更合适),而且返回格式为 { value : “XXX” , done : false } ,当遍历结束则返回 {value : undefined , done : true} 。

最重要的是为这个指针对象添加next( )方法(有没觉得很熟悉,数据结构课程我们经常遇到),当我们第一次调用next( )指针就指向ADT第一个成员。相应的,第二次调用就指向第二个成员。

然后不断地调用next( ) ,就一直遍历下去直到指向ADT结束的位置。

还有很重要的一点(“敲黑板” ),ES6规定只有具有Symbol.iterator属性的ADT才具备可遍历性,而且使用Iterator之前需要调用Symbol.iterator方法(摊手.jpg),其实知道了原理我们也能写个Iterator接口玩玩。
数组,类数组对象,Set和Map内置Iterator接口,使用方法如下

let arr = [ “1” , “2” , “3”]
let it = arr[Symbol.iterator] ( )
it.next( ) // { value: “1” , done: false}
it.next( ) // { value: “2” , done: false}
it.next( ) // { value: “3” ,done: false}
it.next( ) // { value: undefined , done: true}

ES6引用了for … of ,只要具有Symbol.iterator属性就可以用for…of 来遍历,即for…of 循环内部调用的是Iterator接口方法。

let arr = [“1”,”2”,”3”]
for (let v of arr){
     console.log(v)
}

let s = new Set([“1”,”2”,”3”])
for (let a of s){
     console.log(a)
}

另外解构赋值,扩展运算符也是默认调用Iterator接口

既然有引入了for…of,而且许多ADT默认调用Iterator接口,而且使用 it.next( )方式来遍历还不如 for…of来的简单,暴力,这样看起来it.next( )遍历方式貌似有点弱了。

显然这是不对的。


(华丽的分割线)
ES6提供了Generator函数来解决异步编程,当Generator遇上Iterator产生的化学反应——状态机。(Generator需要较长的篇幅来讲解,会专门写篇关于异步编程博客,这里就不深究了)


0x01 对JavaScript所有迭代的方法进行汇总

for循环是最常见的一种写法,大家都很熟悉了。

for-in是用来遍历的是对象的属性(可枚举属性),而在JavaScript中Array可以看成特殊的对象,因此使用for-in遍历数组得到的是数组的索引。在使用for-in的时候,会遍历原型链,所以在一些场景下for的性能高于for-in。

因为for-in会遍历原型链,而且forEach()不支持break和return,所以ES6新增了for-of ,解决了这些问题,而且ES6新增的set,map等数据结构只要内置有Iterator的通通都可以使用 “for-of” 来遍历数据。

最后,以下是ES5为数组定义了5个迭代方法。

  • every
  • filter
  • forEach
  • map
  • some

every( )

对数组每一项执行回调函数,如果该函数对每一项都返回true则返回true。

这里写图片描述


some( ) # 跟every( )有些差别,但使用场景差不多

对数组每一项执行回调函数,如果该函数对任一项返回true则返回true。


filter( ) # 起到过滤功能

对数组每一项执行回调函数,返回该函数会返回true的项组成的数组

这里写图片描述


forEach( )

对数组每一项执行回调函数,没有返回值

(”敲黑板”,考试重点)☞ forEach循环中,break或return不能跳出循环

这里写图片描述


map( )

对数组每一项执行回调函数,返回所有执行结果组成的数组。

这里写图片描述

 
  本文参考《JavaScript高级程序设计》以及阮一峰老师的《ES6标准入门》
  

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值