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 相关文章推荐
动态改变textbox的宽高的js
Oct 26 Javascript
javascript转换字符串为dom对象(字符串动态创建dom)
May 10 Javascript
关于js中alert弹出窗口文本换行问题简单详细说明
Dec 11 Javascript
js操作CheckBoxList实现全选/反选(在客服端完成)
Feb 02 Javascript
面向对象继承实例(a如何继承b问题)(自写)
Jul 01 Javascript
javascript 循环调用示例介绍
Nov 20 Javascript
Asp.Net alert弹出提示信息的几种方法总结
Jan 29 Javascript
AngularJS+Bootstrap实现多文件上传与管理
Nov 08 Javascript
清除js缓存的多种方法总结
Dec 09 Javascript
underscore之Chaining_动力节点Java学院整理
Jul 10 Javascript
jQuery实现键盘回车搜索功能
Jul 25 jQuery
微信小程序开发之左右分栏效果的实例代码
May 20 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输出控制功能在简繁体转换中的应用
2006/10/09 PHP
dede3.1分页文字采集过滤规则详说(图文教程)续四
2007/04/03 PHP
部署PHP项目应该注意的几点事项分享
2013/12/20 PHP
在一个form用一个SUBMIT(或button)分别提交到两个处理表单页面的代码
2007/02/15 Javascript
js url传值中文乱码之解决之道
2009/11/20 Javascript
JQuery的自定义事件代码,触发,绑定简单实例
2013/08/01 Javascript
javascript获取URL参数与参数值的示例代码
2013/12/20 Javascript
JavaScript转换二进制编码为ASCII码的方法
2015/04/16 Javascript
HTML5+setCutomValidity()函数验证表单实例分享
2015/04/24 Javascript
JS实现屏蔽网页右键复制及ctrl+c复制的方法【2种方法】
2016/09/04 Javascript
JavaScript实现经典排序算法之选择排序
2016/12/28 Javascript
JavaScript判断浏览器及其版本信息
2017/01/20 Javascript
jQuery UI Grid 模态框中的表格实例代码
2017/04/01 jQuery
ES6数组的扩展详解
2017/04/25 Javascript
JavaScript数组的5种迭代方法
2017/09/29 Javascript
VUE Error: getaddrinfo ENOTFOUND localhost
2018/05/03 Javascript
Vue-Router的使用方法
2018/09/05 Javascript
jQuery滑动效果实现方法分析
2018/09/05 jQuery
详解mpvue开发微信小程序基础知识
2019/09/23 Javascript
JS实现选项卡插件的两种写法(jQuery和class)
2020/12/30 jQuery
详解阿里Node.js技术文档之process模块学习指南
2021/01/04 Javascript
[01:18]DOTA2超级联赛专访hanci ForLove淘汰感言曝光
2013/06/04 DOTA
[03:57]DOTA2英雄梦之声_第03期_幻影刺客
2014/06/21 DOTA
在Python中处理列表之reverse()方法的使用教程
2015/05/21 Python
Python中type的构造函数参数含义说明
2015/06/21 Python
django 控制页面跳转的例子
2019/08/06 Python
Flask 上传自定义头像的实例详解
2020/01/09 Python
Keras 实现加载预训练模型并冻结网络的层
2020/06/15 Python
Python如何输出百分比
2020/07/31 Python
应届生会计求职信
2013/11/11 职场文书
学习新党章思想汇报
2014/01/09 职场文书
个人社会实践自我鉴定
2014/03/24 职场文书
法制宣传标语
2014/06/23 职场文书
教师节感恩老师演讲稿
2014/08/28 职场文书
淘宝好评语句大全
2014/12/31 职场文书
公司开业主持词
2015/07/02 职场文书