做者:Brandon Morelli
译者:前端小智
来源:Medium
点赞再看,养成习惯本文
GitHub
https://github.com/qq44924588... 上已经收录,更多往期高赞文章的分类,也整理了不少个人文档,和教程资料。欢迎Star和完善,你们面试能够参照考点复习,但愿咱们一块儿有点东西。html
本文旨在分析理解 Iterators。 Iterators 是 JS中的新方法,能够用来循环任意集合。 在ES6中登场的Iterators。因其可被普遍使用,而且已在多处场景派上用场,
咱们将从概念上理解迭代器是什么,以及在何处使用它们和示例。咱们还将看到它在JS 中的一些实现。前端
假设有这样数组git
const myFavouriteAuthors = [ 'Neal Stephenson', 'Arthur Clarke', 'Isaac Asimov', 'Robert Heinlein' ];
在某些状况下,但愿返回数组中的全部单独值,以便在屏幕上打印它们、操做它们或对它们执行某些操做。es6
如何处理? 简单方法就是使用 for
, while
, for-of
方法。github
以下:面试
如今,假设你拥有一个自定义数据结构来保存全部authors
数组
myFavouriteAuthors
是一个对象,它包含另外一个对象 allAuthors
。allAuthors
包含三个数组,其中包含 fiction
、scienceFiction
和 fantasy
。服务器
如今,若是要求你循环遍历 myFavouriteAuthors
以得到全部的author
,你的方法是什么? 你可能会尝试一些循环组合来得到全部数据。微信
可是,若是你这样作了 ——数据结构
for (let author of myFavouriteAuthors) { console.log(author) } // TypeError: {} is not iterable
你将获得一个类型错误,说明该对象不可迭代。让咱们看看什么是可迭代的,以及如何使对象可迭代。
你们都说简历没项目写,我就帮你们找了一个项目,还附赠【搭建教程】。
我和阿里云合做服务器,折扣价比较便宜:89/年,223/3年,比学生9.9每个月还便宜,买了搭建个项目,熟悉技术栈比较香(老用户用家人帐号买就行了,我用我妈的)推荐买三年的划算点,点击本条就能够查看。
在上一节中看到了问题,从咱们的自定义对象中获取全部的author
是不容易的。咱们须要某种方法,经过它咱们能够有序地获取内部数据。
咱们在 myFavouriteAuthors
中添加一个返回全部做者的方法 getAllAuthors
。如:
这是一个简单的方法。它帮咱们完成了获取全部author
的功能。可是,这种实现可能会出现一些问题:
getAllAuthors
的名称很是具体。若是其余人正在建立本身的 myFavouriteAuthors
,他们可能会将其命名为retrieveAllAuthors
。getAllAuthors
。getAllAuthors
返回的是字符串数组,若是另外一个开发人员以这种格式返回一个对象数组,该怎么办:[ {name: 'Agatha Christie'}, {name: 'J. K. Rowling'}, ... ]
开发人员必须知道返回全部数据的方法的确切名称和返回类型。
若是咱们规定方法的名称和它的返回类型是固定不变的呢?
让咱们将这个方法命名为 --- iteratorMethod
ECMA 也采起了相似的步骤来标准化在定制对象上循环的过程。可是,ECMA 没有使用名称 iteratorMethod
,而是使用名称 Symbol.iterator。
Symbols 提供的名称是惟一的,不能与其余属性名称冲突。同时,Symbol.iterator 返回一个名为迭代器的对象,这个迭代器将拥有一个名为next
的方法,该方法将返回一个具备键值为 value
和 done
的对象。
值键 value
包含当前值,它能够是任何类型的,done
是布尔值,它表示是否获取了全部的值。
下图能够帮助创建可迭代对象、迭代器和next
之间的关系,这种关系称为迭代协议。
根据Axel Rauschmayer博士的《探索JS》一书:
Symbol.iterator
的方法来实现,该方法是迭代器的工厂,也就是说,它将建立迭代器。所以,正如咱们在上一节学到的,咱们须要实现一个名为Symbol.iterator
的方法
在第4行,咱们建立迭代器。它是一个定义了next
方法的对象。next
方法根据step
变量返回值。在第25行,咱们检索iterator
,27 行,咱们调用next
方法,直到 done
的值为 true。
这正是for-of
循环中发生的事情,for-of
接受一个迭代器,并建立它的迭代器,它会一直调用next(),直到 done
为 true。
你们都说简历没项目写,我就帮你们找了一个项目,还附赠【搭建教程】。
我和阿里云合做服务器,折扣价比较便宜:89/年,223/3年,比学生9.9每个月还便宜,买了搭建个项目,熟悉技术栈比较香(老用户用家人帐号买就行了,我用我妈的)推荐买三年的划算点,点击本条就能够查看。
JS 中的不少对象都是可迭代的。它们可能不是很好的察觉,可是若是仔细检查,就会发现迭代的特征:
arguments
—— 函数中相似数组的特殊变量JS中使用迭代的其余一些结构是:
for-of
-- for-of 循环须要一个可迭代的对象,不然,它将抛出一个类型错误。for (const value of iterable) { ... }
const array = ['a', 'b', 'c', 'd', 'e'];
const [first, ,third, ,last] = array;
等价于:
const array = ['a', 'b', 'c', 'd', 'e']; const iterator = array[Symbol.iterator](); const first = iterator.next().value iterator.next().value // Since it was skipped, so it's not assigned const third = iterator.next().value iterator.next().value // Since it was skipped, so it's not assigned const last = iterator.next().value
const array = ['a', 'b', 'c', 'd', 'e']; const newArray = [1, ...array, 2, 3];
等价于:
const array = ['a', 'b', 'c', 'd', 'e']; const iterator = array[Symbol.iterator](); const newArray = [1]; for (let nextValue = iterator.next(); nextValue.done !== true; nextValue = iterator.next()) { newArray.push(nextValue.value); } newArray.push(2) newArray.push(3)
Promise.all
和 Promise.race
接受可迭代对象下面是一个实现,它使myFavouriteAuthors
具备可迭代性:
const myFavouriteAuthors = { allAuthors: { fiction: [ 'Agatha Christie', 'J. K. Rowling', 'Dr. Seuss' ], scienceFiction: [ 'Neal Stephenson', 'Arthur Clarke', 'Isaac Asimov', 'Robert Heinlein' ], fantasy: [ 'J. R. R. Tolkien', 'J. K. Rowling', 'Terry Pratchett' ], }, [Symbol.iterator]() { // 获取数组中的全部做者 const genres = Object.values(this.allAuthors); // 存储当前类型和索引 let currentAuthorIndex = 0; let currentGenreIndex = 0; return { // Implementation of next() next() { // 根据当前的索引获取对应的做者信息 const authors = genres[currentGenreIndex]; // 当遍历完数组 authors是,oNotHaveMoreAuthors 为 true const doNothaveMoreAuthors = !(currentAuthorIndex < authors.length); if (doNothaveMoreAuthors) { // 加一继续访问下一个 currentGenreIndex++; // 重置 currentAuthorIndex = 0; } // 若是全部 genres 都遍历完告终,那么咱们须要告诉迭代器不能提供更多的值。 const doNotHaveMoreGenres = !(currentGenreIndex < genres.length); if (doNotHaveMoreGenres) { return { value: undefined, done: true }; } // 若是一切正常,从当genre 返回 做者和当前做者索引,以便下次,下一个做者能够返回。 return { value: genres[currentGenreIndex][currentAuthorIndex++], done: false } } }; } }; for (const author of myFavouriteAuthors) { console.log(author); } console.log(...myFavouriteAuthors)
经过本文得到的知识,你能够很容易地理解迭代器是如何工做的,这种逻辑可能有点难以理解。所以,理解这个概念的最佳方法是多多敲死代码,多多验证!
代码部署后可能存在的BUG无法实时知道,过后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给你们推荐一个好用的BUG监控工具 Fundebug。
文章每周持续更新,能够微信搜索「 大迁世界 」第一时间阅读和催更(比博客早一到两篇哟),本文 GitHub https://github.com/qq449245884/xiaozhi 已经收录,整理了不少个人文档,欢迎Star和完善,你们面试能够参照考点复习,另外关注公众号,后台回复福利,便可看到福利,你懂的。