如何在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 相关文章推荐
js跨域问题之跨域iframe自适应大小实现代码
Jul 17 Javascript
Extjs TimeField 显示正常时间格式的代码
Jun 28 Javascript
在Javascript中 声明时用"var"与不用"var"的区别
Apr 15 Javascript
禁用键盘上的(全局)指定键兼容iE、Chrome、火狐
May 14 Javascript
JavaScript异步编程:异步数据收集的具体方法
Aug 19 Javascript
javascript实现json页面分页实例代码
Feb 20 Javascript
javascript每日必学之基础入门
Feb 16 Javascript
jQuery使用模式窗口实现在主页面和子页面中互相传值的方法
Mar 01 Javascript
javascript鼠标滑过显示二级菜单特效
Nov 18 Javascript
JavaScript实现秒杀时钟倒计时
Sep 29 Javascript
CountUp.js实现数字滚动增值效果
Oct 17 Javascript
JavaScript 如何计算文本的行数的实现
Sep 14 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
SONY ICF-SW55的电路分析
2021/03/02 无线电
php cURL和Rolling cURL并发方式比较
2013/10/30 PHP
curl不使用文件存取cookie php使用curl获取cookie示例
2014/01/26 PHP
php向js函数传参的几种方法
2014/08/10 PHP
PHP采用curl模仿用户登陆新浪微博发微博的方法
2014/11/07 PHP
php面向对象与面向过程两种方法给图片添加文字水印
2015/08/26 PHP
PHP简单实现循环链表功能示例
2017/11/10 PHP
Yii框架中使用PHPExcel的方法分析
2019/07/25 PHP
基于javascript滚动图片具体实现
2013/11/18 Javascript
JS动态增加删除UL节点LI及相关内容示例
2014/05/21 Javascript
详解JavaScript编程中正则表达式的使用
2015/10/25 Javascript
JavaScript ParseFloat()方法
2015/12/18 Javascript
javascript RegExp 使用说明
2016/05/21 Javascript
nodejs加密Crypto的实例代码
2016/07/07 NodeJs
jquery attr()设置和获取属性值实例教程
2016/09/25 Javascript
浅谈js在html中的加载执行顺序,多个jquery ready执行顺序
2016/11/26 Javascript
从零开始在NPM上发布一个Vue组件的方法步骤
2018/12/20 Javascript
Vue组件教程之Toast(Vue.extend 方式)详解
2019/01/27 Javascript
微信小程序五子棋游戏的棋盘,重置,对弈实现方法【附demo源码下载】
2019/02/20 Javascript
微信小程序rich-text富文本用法实例分析
2019/05/20 Javascript
Python生成器(Generator)详解
2015/04/13 Python
Python使用matplotlib绘制动画的方法
2015/05/20 Python
Python实现文件按照日期命名的方法
2015/07/09 Python
python和pygame实现简单俄罗斯方块游戏
2021/02/19 Python
Python中PyQt5/PySide2的按钮控件使用实例
2019/08/17 Python
django filter过滤器实现显示某个类型指定字段不同值方式
2020/07/16 Python
关于多种方式完美解决Python pip命令下载第三方库的问题
2020/12/21 Python
澳大利亚婴儿礼品公司:The Baby Gift Company
2018/11/04 全球购物
美国最大最全的亚洲购物网站:美国亚米网(Yamibuy)
2020/05/05 全球购物
后勤园长自我鉴定
2013/10/17 职场文书
文明青少年标兵事迹材料
2014/01/28 职场文书
建筑安全标语
2014/06/07 职场文书
大国崛起英国观后感
2015/06/02 职场文书
解决Navicat for Mysql连接报错1251的问题(连接失败)
2021/05/27 MySQL
Python 数据可视化之Matplotlib详解
2021/11/02 Python
Python可视化学习之matplotlib内置单颜色
2022/02/24 Python