如何在JavaScript中优雅的提取循环内数据详解


Posted in Javascript onMarch 04, 2019

前言

在本文中,我们将介绍两种提取循环内数据的方法:内部迭代和外部迭代。分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧

循环

举个例子,假设有一个函数 logFiles():

const fs = require('fs');
const path = require('path');

function logFiles(dir) {
 for (const fileName of fs.readdirSync(dir)) { // (A)
 const filePath = path.resolve(dir, fileName);
 console.log(filePath);
 const stats = fs.statSync(filePath);
 if (stats.isDirectory()) {
  logFiles(filePath); // (B)
 }
 }
}
logFiles(process.argv[2]);

从 A 行开始的循环用来记录文件路径。它是 for-of 循环和递归的组合(递归调用在 B 行)。

如果你发现循环内的某些数据(迭代文件)有用,但又不想记录它,那应该怎么办?

内部迭代

提取循环内数据的第一个方法是内部迭代:

const fs = require('fs');
const path = require('path');

function logFiles(dir, callback) {
 for (const fileName of fs.readdirSync(dir)) {
 const filePath = path.resolve(dir, fileName);
 callback(filePath); // (A)
 const stats = fs.statSync(filePath);
 if (stats.isDirectory()) {
  logFiles(filePath, callback);
 }
 }
}
logFiles(process.argv[2], p => console.log(p));

这种迭代方式与Array的 .forEach()类似:logFiles() 内实现循环并对每个迭代值(行A)调用 callback。

外部迭代

内部迭代的替代方案是外部迭代:我们实现了一个iterable,可以用生成器帮助我们实现:

const fs = require('fs');
const path = require('path');

function* logFiles(dir) {
 for (const fileName of fs.readdirSync(dir)) {
 const filePath = path.resolve(dir, fileName);
 yield filePath;
 const stats = fs.statSync(filePath);
 if (stats.isDirectory()) {
  yield* logFiles(filePath); // (A)
 }
 }
}
for (const p of logFiles(process.argv[2])) {
 console.log(p);
}

如果是内部迭代,logFiles() 会调用我们(“推”给我们)。而这一次,换我们来调用它了(“拉”过来)。

请注意,在生成器中,必须通过 yield*  进行递归调用(第A行):如果只调用 logFiles() 那么它会返回一个iterable。但我们想要的是在该 iterable 中 yield 每个项目。这就是 yield* 的作用。

生成器有一个非常好的特性,就是处理过程能够与内部迭代一样互锁:每当 logFiles() 创建另一个  filePath  时,我们能够立即查看它,然后 logFiles() 继续。这是一种简单的协作式多任务处理,其中 yield 暂停当前任务并切换到另一个任务。

扩展阅读

Chapter “Iterables and iterators” in “Exploring ES6”.
Chapter “Generators” in “Exploring ES6”.

原文:http://2ality.com/2018/04/extracting-loops.html

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
QUnit jQuery的TDD框架
Nov 04 Javascript
JS嵌套函数调用上下文的问题解决
Mar 26 Javascript
AngularJS入门教程之学习环境搭建
Dec 06 Javascript
flash+jQuery实现可关闭及重复播放的压顶广告
Apr 15 Javascript
全面了解addEventListener和on的区别
Jul 14 Javascript
详解基于angular路由的requireJs按需加载js
Jan 20 Javascript
Vue.js父与子组件之间传参示例
Feb 28 Javascript
JavaScript的六种继承方式(推荐)
Jun 26 Javascript
原生JS实现轮播图效果
Oct 12 Javascript
利用jqgrid实现上移下移单元格功能
Nov 07 Javascript
vue无限轮播插件代码实例
May 10 Javascript
vue $mount 和 el的区别说明
Sep 11 Javascript
iview tabs 顶部导航栏和模块切换栏的示例代码
Mar 04 #Javascript
Vuex mutitons和actions初使用详解
Mar 04 #Javascript
JS重学系列之聊聊new操作符
Mar 04 #Javascript
jQuery实现的导航条点击后高亮显示功能示例
Mar 04 #jQuery
ES10 特性的完整指南小结
Mar 04 #Javascript
node.js使用express框架进行文件上传详解
Mar 03 #Javascript
微信小程序新手教程之启动页的重要性
Mar 03 #Javascript
You might like
php验证手机号码(支持归属地查询及编码为UTF8)
2013/02/01 PHP
实例讲解PHP设计模式编程中的简单工厂模式
2016/02/29 PHP
javascript eval函数深入认识
2009/02/21 Javascript
javascript addBookmark 加入收藏 多浏览器兼容
2009/08/15 Javascript
深入理解jQuery中live与bind方法的区别
2013/12/18 Javascript
js 获取页面高度和宽度兼容 ie firefox chrome等
2014/05/14 Javascript
jQuery循环动画与获取组件尺寸的方法
2015/02/02 Javascript
微信小程序上滑加载下拉刷新(onscrollLower)分批加载数据(二)
2017/05/11 Javascript
jQuery Position方法使用和兼容性
2017/08/23 jQuery
JS中原始值和引用值的储存方式示例详解
2018/03/23 Javascript
微信小程序如何获取用户收货地址
2018/11/27 Javascript
微信 jssdk 签名错误invalid signature的解决方法
2019/01/14 Javascript
详解基于 Node.js 的轻量级云函数功能实现
2019/07/08 Javascript
JavaScript遍历数组和对象的元素简单操作示例
2019/07/09 Javascript
[01:43]深扒TI7聊天轮盘语音出处4
2017/05/11 DOTA
python在多玩图片上下载妹子图的实现代码
2013/08/13 Python
python使用正则表达式提取网页URL的方法
2015/05/26 Python
Python 网页解析HTMLParse的实例详解
2017/08/10 Python
浅述python2与python3的简单区别
2018/09/19 Python
python编程使用协程并发的优缺点
2018/09/20 Python
Django如何自定义分页
2018/09/25 Python
python将字符串以utf-8格式保存在txt文件中的方法
2018/10/30 Python
Python中对数组集进行按行打乱shuffle的方法
2018/11/08 Python
Django实现发送邮件功能
2019/07/18 Python
Python + Requests + Unittest接口自动化测试实例分析
2019/12/12 Python
HTML5的结构和语义(2):结构
2008/10/17 HTML / CSS
Boston Proper官网:美国女装品牌
2017/10/30 全球购物
APM Monaco中国官网:来自摩纳哥珠宝品牌
2017/12/27 全球购物
在子网210.27.48.21/30种有多少个可用地址?分别是什么?
2014/07/27 面试题
介绍一下Linux文件的记录形式
2012/04/18 面试题
装潢设计实习自我鉴定
2013/09/19 职场文书
机电一体化毕业生求职信
2013/11/02 职场文书
优秀班集体申报材料
2014/12/25 职场文书
离职告别感言
2015/08/04 职场文书
python中pandas.read_csv()函数的深入讲解
2021/03/29 Python
MySql学习笔记之事务隔离级别详解
2021/05/12 MySQL