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 相关文章推荐
表单提交验证类
Jul 14 Javascript
在VS2008中使用jQuery智能感应的方法
Dec 30 Javascript
JS控制日期显示的小例子
Nov 23 Javascript
jQuery学习笔记之jQuery构建函数的7种方法
Jun 03 Javascript
用javascript读取xml文件读取节点数据
Aug 12 Javascript
js实现楼层效果的简单实例
Jul 15 Javascript
详解angularJS自定义指令间的相互交互
Jul 05 Javascript
详解Webpack + ES6 最新环境搭建与配置
Jun 04 Javascript
layer.open 按钮的点击事件关闭方法
Aug 17 Javascript
使用layui 渲染table数据表格的实例代码
Aug 19 Javascript
使用gulp构建前端自动化的方法示例
Dec 25 Javascript
vuejs简单验证码功能完整示例
Jan 08 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 函数语法介绍一
2009/06/14 PHP
php zip文件解压类代码
2009/12/02 PHP
async和DOM Script文件加载比较
2014/07/20 PHP
PHP和Mysql中转UTF8编码问题汇总
2015/10/10 PHP
PHP新特性之字节码缓存和内置服务器
2017/08/11 PHP
javascript中数组的定义及使用实例
2015/01/21 Javascript
JavaScript中用sort()方法对数组元素进行排序的操作
2015/06/09 Javascript
jQuery实现图片轮播效果代码(基于jquery.pack.js插件)
2016/06/02 Javascript
浅谈JavaScript的内置对象和浏览器对象
2016/06/03 Javascript
Query常用DIV操作获取和设置长度宽度的实现方法
2016/09/19 Javascript
JSON与XML的区别对比及案例应用
2016/11/11 Javascript
js使用Replace结合正则替换重复出现的字符串功能示例
2016/12/27 Javascript
Angular2 组件交互实例详解
2017/08/24 Javascript
vue中实现滚动加载更多的示例
2017/11/08 Javascript
浅谈vuepress 踩坑记
2018/04/18 Javascript
vue组件中的数据传递方法
2018/05/14 Javascript
Node+OCR实现图像文字识别功能
2018/11/26 Javascript
如何将Node.js中的回调转换为Promise
2020/11/10 Javascript
[50:04]DOTA2上海特级锦标赛D组小组赛#2 Liquid VS VP第二局
2016/02/28 DOTA
由面试题加深对Django的认识理解
2019/07/19 Python
Python下应用opencv 实现人脸检测功能
2019/10/24 Python
使用OpenCV获取图像某点的颜色值,并设置某点的颜色
2020/06/02 Python
python代码中怎么换行
2020/06/17 Python
python中怎么表示空值
2020/06/19 Python
Python基于argparse与ConfigParser库进行入参解析与ini parser
2021/02/02 Python
利用CSS3实现单选框动画特效示例代码
2016/09/26 HTML / CSS
html5 Canvas画图教程(2)—画直线与设置线条的样式如颜色/端点/交汇点
2013/01/09 HTML / CSS
介绍一下linux文件系统分配策略
2012/11/17 面试题
经销商培训邀请函
2014/01/21 职场文书
2014年母亲节寄语
2014/05/07 职场文书
机关党员三严三实心得体会
2014/10/13 职场文书
教师个人成长总结
2015/02/11 职场文书
检讨书范文大全
2015/05/07 职场文书
火锅店的开业营销方案范本!
2019/07/05 职场文书
golang 定时任务方面time.Sleep和time.Tick的优劣对比分析
2021/05/05 Golang
css实现两栏布局,左侧固定宽,右侧自适应的多种方法
2021/08/07 HTML / CSS