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 相关文章推荐
Firefox+FireBug使JQuery的学习更加轻松愉快
Jan 01 Javascript
自写的一个jQuery圆角插件
Oct 26 Javascript
javascript实现十六进制颜色值(HEX)和RGB格式相互转换
Jun 20 Javascript
Javascript访问器属性实例分析
Dec 30 Javascript
基于jquery实现图片上传本地预览功能
Jan 08 Javascript
jQuery简单实现彩色云标签效果示例
Aug 01 Javascript
Bootstrap和Java分页实例第二篇
Dec 23 Javascript
干货!教大家如何选择Vue和React
Mar 13 Javascript
jQuery实现列表的增加和删除功能
Jun 14 jQuery
在小程序中使用canvas的方法示例
Sep 17 Javascript
vue两组件间值传递 $router.push实现方法
May 15 Javascript
详解钉钉小程序组件之自定义模态框(弹窗封装实现)
Mar 07 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
使用 PHPMAILER 发送邮件实例应用
2012/11/07 PHP
destoon实现调用当前栏目分类及子分类和三级分类的方法
2014/08/21 PHP
在IE中调用javascript打开Excel的代码(downmoon原作)
2007/04/02 Javascript
asp.net+js 实现无刷新上传解析csv文件的代码
2010/05/17 Javascript
Function.prototype.call.apply结合用法分析示例
2013/07/03 Javascript
javascript闭包入门示例
2014/04/30 Javascript
教你如何使用PHP输出中文JSON字符串
2014/05/22 Javascript
node.js中的url.parse方法使用说明
2014/12/10 Javascript
javascript实现抽奖程序的简单实例
2016/06/07 Javascript
浅谈jQuery before和insertBefore的区别
2016/12/04 Javascript
Bootstrap popover 实现鼠标移入移除显示隐藏功能方法
2018/01/24 Javascript
jQuery实现参数自定义的文字跑马灯效果
2018/08/15 jQuery
JavaScript中的null和undefined用法解析
2019/09/30 Javascript
使用JavaScrip模拟实现仿京东搜索框功能
2019/10/16 Javascript
基于vue中的scoped坑点解说
2020/09/04 Javascript
vuecli项目构建SSR服务端渲染的实现
2020/10/30 Javascript
快速解决vue2+vue-cli3项目ie兼容的问题
2020/11/17 Vue.js
[24:42]VP vs TNC Supermajor小组赛B组 BO3 第三场 6.2
2018/06/03 DOTA
python基础入门详解(文件输入/输出 内建类型 字典操作使用方法)
2013/12/08 Python
cmd运行python文件时对结果进行保存的方法
2018/05/16 Python
PyCharm安装第三方库如Requests的图文教程
2018/05/18 Python
python字符串查找函数的用法详解
2019/07/08 Python
python中单下划线(_)和双下划线(__)的特殊用法
2019/08/29 Python
Django 设置多环境配置文件载入问题
2020/02/25 Python
python zip,lambda,map函数代码实例
2020/04/04 Python
Python Dict找出value大于某值或key大于某值的所有项方式
2020/06/05 Python
python性能测试工具locust的使用
2020/12/28 Python
北美领先的智能产品购物网站:Wellbots
2018/06/11 全球购物
牦牛毛户外探险服装:Kora
2019/02/08 全球购物
美国电子产品主要品牌的授权在线零售商:DataVision
2019/03/23 全球购物
G-Form护具官方网站:美国运动保护装备
2019/09/04 全球购物
EJB的基本架构
2016/09/22 面试题
财政专业求职信范文
2014/02/19 职场文书
药品营销策划方案
2014/06/15 职场文书
个人四风对照检查材料
2014/09/26 职场文书
爱国主义教育主题班会
2015/08/13 职场文书