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 防止刷新,后退,关闭
Aug 07 Javascript
JavaScript动态创建div属性和样式示例代码
Oct 09 Javascript
javascript委托(Delegate)blur和focus用法实例分析
May 26 Javascript
jquery读取xml文件实现省市县三级联动的方法
May 29 Javascript
JavaScript实现跨浏览器的添加及删除事件绑定函数实例
Aug 04 Javascript
jquery实现清新实用的网页菜单效果
Aug 28 Javascript
分享五个有用的jquery小技巧
Oct 08 Javascript
jquery插件格式实例分析
Jun 16 Javascript
jQuery简单实现tab选项卡切换效果
Jun 20 Javascript
使用命令行工具npm新创建一个vue项目的方法
Dec 27 Javascript
浅谈Vue CLI 3结合Lerna进行UI框架设计
Apr 14 Javascript
vue导航栏部分的动态渲染实例
Nov 01 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
Laravel中使用阿里云OSS Composer包分享
2015/02/10 PHP
thinkPHP3.2使用RBAC实现权限管理的实现
2019/08/27 PHP
js RuntimeObject() 获取ie里面自定义函数或者属性的集合
2010/11/23 Javascript
JavaScript中的isXX系列是否继续使用的分析
2011/04/16 Javascript
基于jQuery仿淘宝产品图片放大镜代码分享
2020/06/23 Javascript
javascript实现自动填写表单实例简析
2015/12/02 Javascript
非常漂亮的相册集 使用jquery制作相册集
2016/04/28 Javascript
利用vue-router实现二级菜单内容转换
2016/11/30 Javascript
JS求解三元一次方程组值的方法
2017/01/03 Javascript
js判断PC端与移动端跳转
2020/12/24 Javascript
js下拉菜单生成器dropMenu使用方法详解
2017/08/01 Javascript
详解如何让InstantClick兼容MathJax、百度统计等
2017/09/12 Javascript
vue中Axios的封装与API接口的管理详解
2018/08/09 Javascript
菊花转动的jquery加载动画效果
2018/08/19 jQuery
Vue使用localStorage存储数据的方法
2019/05/27 Javascript
解决vue页面刷新,数据丢失的问题
2020/11/24 Vue.js
python中使用sys模板和logging模块获取行号和函数名的方法
2014/04/15 Python
Python入门教程之运算符与控制流
2016/08/17 Python
Python KMeans聚类问题分析
2018/02/23 Python
解决webdriver.Chrome()报错:Message:'chromedriver' executable needs to be in Path
2019/06/12 Python
在TensorFlow中屏蔽warning的方式
2020/02/04 Python
详解CSS3中Media Queries的相关使用
2015/07/17 HTML / CSS
Daisy London官网:英国最大的首饰集团IBB旗下
2019/02/28 全球购物
葡萄牙航空官方网站:TAP Air Portugal
2019/10/31 全球购物
说说在weblogic中开发消息Bean时的persistent与non-persisten的差别
2013/04/07 面试题
老师自我鉴定范文
2013/12/25 职场文书
家长会学生家长演讲稿
2013/12/29 职场文书
社区七一党员活动方案
2014/01/25 职场文书
全民健身日活动方案
2014/01/29 职场文书
小学生家长评语集锦
2014/01/30 职场文书
公司中层干部的自我评价分享
2014/03/01 职场文书
计算机科学系职业生涯规划书
2014/03/08 职场文书
交通事故赔偿协议书范本
2014/04/15 职场文书
广场舞大赛策划方案
2014/05/31 职场文书
2014财务年终工作总结
2014/12/08 职场文书
win11无线投屏在哪设置? win11无线投屏功能的使用方法
2022/04/08 数码科技