JavaScript中yield实用简洁实现方式


Posted in Javascript onJune 12, 2010

刚才忽然灵机一动,迭代器我们很少会真的直接傻乎乎的next去遍历的,那为什么一定要实现这个傻乎乎的next呢?直接实现each,这样,这样反过来,Yeah,一通百通,不一会儿就写出了第一个超简洁版本:

function yieldHost(yieldFunction) 
{ 
return function (processer) 
{ 
var yield = function (result) 
{ 
processer(result) 
}; 
yieldFunction(yield); 
}; 
}

思路一换,代码真简洁。
先附上例子,然后来谈原理。
首先我们需要一个函数来进行枚举,像这样:
function fun(yield) 
{ 
for (var i = 0; i < 100; i++) 
yield(i); 
}

或是这样:
function fun(yield) 
{ 
yield(1); 
yield(2); 
yield(3); 
}

由于实现方式与C#的不同,所以在循环体内也不用什么yield break或是yield continue这样的语法,直接break或是continue就好了。
然后是实际的运用,yieldHost函数可以将上面的符合要求的fun函数转换为一个枚举器:
var enumerator = yieldHost(fun);
这个枚举器其实也是一个函数,像jQuery的each函数一样,接收一个处理函数来处理枚举:
enumerator(function (item) 
{ 
window.alert(item); 
});

接下来谈谈原理。
对于传统的枚举器来说,我们会认为枚举器应该在每次调用返回一个值,这就是next方法,但就像陈子瀚说的,这需要在yield的时候把函数停住,虽然可以实现,但真的很麻烦。
但!事实上我发现,大多数时候,我们都是用foreach这样的语法来访问枚举器的。这样一来就给了我一个非常讨巧的办法,不实现next方法,而是实现each方法。
each方法和next的方法的区别在哪里呢?熟悉jQuery的朋友就会知道,each方法其实可以视为将next倒过来,不是返回枚举值,而是接收一个函数,把枚举值当作参数传进去。
正是这一倒,所有问题都迎刃而解了。我们没有必要去暂停一个函数的执行,只需要将处理枚举值的逻辑注到这个函数里面去就完了。所以事实上这里的yieldHost就是完成了一个倒装的工作,把enumerator接收的那个函数(也就是window.alert( item ),注到了枚举函数中(即fun)。最终执行的效果就像是这样:
function fun(yield) 
{ 
window.alert(1); 
window.alert(2); 
window.alert(3); 
}

所以就诞生了这个超简洁的实现。
有了这个超简洁的实现,下一步就是实现像jQuery的each方法一样的return true代表break和return false代表continue的功能了,只有具备了这样的功能,才能处理无穷集,或是实现TakeWhile之类的功能。
老实说我对JavaScript的研究并不透彻,只想到了一个使用异常打断的办法,这就是第二个版本的yieldHost:
function yieldHost(yieldFunction) 
{ 
var exception = Math.random(); 
return function (processer) 
{ 
try 
{ 
yieldFunction(function (result) 
{ 
if (processer(result)) 
throw exception; 
}); 
} 
catch (e) 
{ 
if (e !== exception) 
throw e; 
} 
}; 
}

显然这并不完美,但我实在想不出更好的办法。
接下来在这个基础上实现Select、Where什么,其实是非常简单的事情,给出一个我的Select的实现:
function Select(enumerator, selector) 
{ 
return function (fun) 
{ 
enumerator(function (item) 
{ 
return fun(selector(item)); 
}); 
} 
}

至于,这个Select怎么修改成连写的版本,即:
enumerator.Select( selector )( processor );
我觉得这对JavaScript而言真不是一件很难的事情啊。。。。
只是,过早的引入语法友好,会把JavaScript变得很复杂难看。所以,这个留给大家去玩吧。

Javascript 相关文章推荐
实现变速回到顶部的JavaScript代码
May 09 Javascript
javascript定义变量时加var与不加var的区别
Dec 22 Javascript
JavaScript中setFullYear()方法的使用详解
Jun 11 Javascript
JS使用正则表达式除去字符串中重复字符的方法
Nov 05 Javascript
Bootstrap弹出框(modal)垂直居中的问题及解决方案详解
Jun 12 Javascript
简单分析javascript中的函数
Sep 10 Javascript
js中用cssText设置css样式的简单方法
Sep 19 Javascript
js上下视差滚动简单实现代码
Mar 07 Javascript
vue-router单页面路由
Jun 17 Javascript
利用Ionic2 + angular4实现一个地区选择组件
Jul 27 Javascript
js通过循环多张图片实现动画效果
Dec 19 Javascript
Openlayers3实现车辆轨迹回放功能
Sep 29 Javascript
EasySlider 基于jQuery功能强大简单易用的滑动门插件
Jun 11 #Javascript
JavaScript 开发规范要求(图文并茂)
Jun 11 #Javascript
cnblogs TagCloud基于jquery的实现代码
Jun 11 #Javascript
Js setInterval与setTimeout(定时执行与循环执行)的代码(可以传入参数)
Jun 11 #Javascript
js鼠标左右键 键盘值小结
Jun 11 #Javascript
JavaScript接口实现代码 (Interfaces In JavaScript)
Jun 11 #Javascript
JavaScript的单例模式 (singleton in Javascript)
Jun 11 #Javascript
You might like
基于php iconv函数的使用详解
2013/06/09 PHP
PHP 获取ip地址代码汇总
2015/07/05 PHP
php正则表达式基本知识与应用详解【经典教程】
2017/04/17 PHP
在b/s开发中经常用到的javaScript技术
2006/08/23 Javascript
推荐dojo学习笔记
2007/03/24 Javascript
jquery应该如何来设置改变按钮input的onclick事件
2012/12/10 Javascript
jQuery学习笔记之jQuery构建函数的7种方法
2014/06/03 Javascript
AngularJS下对数组的对比分析
2016/08/24 Javascript
jquery获取下拉框中的循环值
2017/02/08 Javascript
Vue-resource实现ajax请求和跨域请求示例
2017/02/23 Javascript
详解使用grunt完成requirejs的合并压缩和js文件的版本控制
2017/03/02 Javascript
VueAwesomeSwiper在VUE中的使用以及遇到的一些问题
2018/01/11 Javascript
Ionic学习日记实现验证码倒计时
2018/02/08 Javascript
关于redux-saga中take使用方法详解
2018/02/27 Javascript
关于HTML5的data-*自定义属性的总结
2018/05/05 Javascript
koa2 用户注册、登录校验与加盐加密的实现方法
2019/07/22 Javascript
Vue项目环境搭建详细总结
2019/09/26 Javascript
详解Vue.js 作用域、slot用法(单个slot、具名slot)
2019/10/15 Javascript
Vuex实现数据增加和删除功能
2019/11/11 Javascript
react PropTypes校验传递的值操作示例
2020/04/28 Javascript
JS获取当前时间戳方法解析
2020/08/29 Javascript
Python赋值语句后逗号的作用分析
2015/06/08 Python
详解Python if-elif-else知识点
2018/06/11 Python
python 实现生成均匀分布的点
2019/12/05 Python
pytorch:实现简单的GAN示例(MNIST数据集)
2020/01/10 Python
tensorflow2.0与tensorflow1.0的性能区别介绍
2020/02/07 Python
关于Python不换行输出和不换行输出end=““不显示的问题(亲测已解决)
2020/10/27 Python
里程积分管理买卖交换平台:Points.com
2017/01/13 全球购物
加拿大专业美发产品购物网站:Chatters
2021/02/28 全球购物
华为慧通面试题
2012/09/11 面试题
高校学生干部的自我评价分享
2013/11/04 职场文书
三方合作协议书范本
2014/04/18 职场文书
医院领导班子整改方案
2014/10/01 职场文书
MySQL复制问题的三个参数分析
2021/04/07 MySQL
教你如何使用Python下载B站视频的详细教程
2021/04/29 Python
浅谈Python实现opencv之图片色素的数值运算和逻辑运算
2021/06/23 Python