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与webservice的通信实现代码
Dec 25 Javascript
使用Post提交时须将空格转换成加号的解释
Jan 14 Javascript
javascript使用smipleChart实现简单图表
Jan 02 Javascript
使用javascript提交form表单方法汇总
Jun 25 Javascript
jQuery获取字符串中出现最多的数
Feb 22 Javascript
jquery实现下拉框功能效果【实例代码】
May 06 Javascript
jQuery ztree实现动态树形多选菜单
Aug 12 Javascript
如何给ss bash 写一个 WEB 端查看流量的页面
Mar 23 Javascript
使用JavaScript破解web
Sep 28 Javascript
在Vue中用canvas实现二维码和图片合成海报的方法
Jun 10 Javascript
对Layer弹窗使用及返回数据接收的实例详解
Sep 26 Javascript
vue项目中锚点定位替代方式
Nov 13 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
15种PHP Encoder的比较
2007/03/06 PHP
PHP COOKIE设置为浏览器进程
2009/06/21 PHP
php设计模式之命令模式使用示例
2014/03/02 PHP
在Yii2中使用Pjax导致Yii2内联脚本载入失败的原因分析
2016/03/06 PHP
Joomla简单判断用户是否登录的方法
2016/05/04 PHP
Yii CDBCriteria常用方法实例小结
2017/01/19 PHP
PHP实现的数据对象映射模式详解
2019/03/20 PHP
php传值和传引用的区别点总结
2019/11/19 PHP
一些常用的JS功能函数代码
2009/06/23 Javascript
javascript setTimeout()传递函数参数(包括传递对象参数)
2010/04/07 Javascript
jquery 中多条件选择器,相对选择器,层次选择器的区别
2012/07/03 Javascript
jquery上传插件fineuploader上传文件使用方法(jquery图片上传插件)
2013/12/05 Javascript
javascript 数字格式化输出的实现代码
2013/12/10 Javascript
javaScript中slice函数用法实例分析
2015/06/08 Javascript
基于javascript实现图片懒加载
2016/01/05 Javascript
AngularJS基础 ng-href 指令用法
2016/08/01 Javascript
js+css3制作时钟特效
2016/10/16 Javascript
浅谈对Angular中的生命周期钩子的理解
2017/07/31 Javascript
JavaScript实现的DOM绘制柱状图效果示例
2018/08/08 Javascript
解决Layui数据表格中checkbox位置不居中的方法
2018/08/15 Javascript
Javascript之高级数组API的使用实例
2019/03/08 Javascript
layui导出所有数据的例子
2019/09/10 Javascript
解决Nuxt使用axios跨域问题
2020/07/06 Javascript
jQuery实现异步上传一个或多个文件
2020/08/17 jQuery
python写入并获取剪切板内容的实例
2018/05/31 Python
python3 flask实现文件上传功能
2020/03/20 Python
用Python和WordCloud绘制词云的实现方法(内附让字体清晰的秘笈)
2019/01/08 Python
Python实现删除排序数组中重复项的两种方法示例
2019/01/31 Python
详解centos7+django+python3+mysql+阿里云部署项目全流程
2019/11/15 Python
可视化pytorch 模型中不同BN层的running mean曲线实例
2020/06/24 Python
html5实现输入框fixed定位在屏幕最底部兼容性
2020/07/03 HTML / CSS
新闻系毕业生推荐信
2013/11/16 职场文书
庆祝教师节活动方案
2014/01/31 职场文书
建议书的格式
2014/05/12 职场文书
党的群众路线教育实践活动对照检查材料(四风)
2014/09/27 职场文书
MySQL对数据表已有表进行分区表的实现
2021/11/01 MySQL