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 相关文章推荐
正负小数点后两位浮点数实现原理及代码
Sep 06 Javascript
javascript 通用loading动画效果实例代码
Jan 14 Javascript
jQuery.Highcharts.js绘制柱状图饼状图曲线图
Mar 14 Javascript
JavaScript简单修改窗口大小的方法
Aug 03 Javascript
原生JS改变透明度实现轮播效果
Mar 24 Javascript
jQuery+ajax实现局部刷新的两种方法
Jun 08 jQuery
Javascript实现购物车功能的详细代码
May 08 Javascript
ndm:NPM的桌面GUI应用程序
Oct 15 Javascript
JavaScript页面倒计时功能完整示例
May 15 Javascript
Node.js 在本地生成日志文件的方法
Feb 07 Javascript
vue使用screenfull插件实现全屏功能
Sep 17 Javascript
微信小程序选择图片控件
Jan 19 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添加MySQL数据记录代码
2008/06/07 PHP
PHP中去掉字符串首尾空格的方法
2012/05/19 PHP
php中is_null,empty,isset,unset 的区别详细介绍
2013/04/28 PHP
使用PHP接收POST数据,解析json数据
2013/06/28 PHP
WampServer下安装多个版本的PHP、mysql、apache图文教程
2015/01/07 PHP
PHP借助phpmailer发送邮件
2015/05/11 PHP
php编写的抽奖程序中奖概率算法
2015/05/14 PHP
javascript学习笔记(十二) RegExp类型介绍
2012/06/20 Javascript
多个$(document).ready()的执行顺序实例分析
2014/07/26 Javascript
node.js中的fs.readSync方法使用说明
2014/12/17 Javascript
jquery实现删除一个元素后面的所有元素功能
2015/12/21 Javascript
JS Attribute属性操作详解
2016/05/19 Javascript
JS检测页面中哪个HTML标签触发点击事件的方法
2016/06/17 Javascript
AngularJS表单验证中级篇(3)
2016/09/28 Javascript
jquery实现文字单行横移或翻转(上下、左右跳转)
2017/01/08 Javascript
兼容浏览器的js事件绑定函数(详解)
2017/05/09 Javascript
详解HTTPS 的原理和 NodeJS 的实现
2017/07/04 NodeJs
Vue header组件开发详解
2018/01/26 Javascript
详解angularjs跨页面传参遇到的一些问题
2018/11/01 Javascript
微信小程序webview实现长按点击识别二维码功能示例
2019/01/24 Javascript
关于Vue源码vm.$watch()内部原理详解
2019/04/26 Javascript
python使用tornado实现登录和登出
2018/07/28 Python
django利用request id便于定位及给日志加上request_id
2018/08/26 Python
python随机生成大小写字母数字混合密码(仅20行代码)
2020/02/01 Python
opencv python如何实现图像二值化
2020/02/03 Python
python与c语言的语法有哪些不一样的
2020/09/13 Python
python和opencv构建运动检测器的实现
2021/03/03 Python
详解如何用HTML5 Canvas API控制图片的缩放变换
2016/03/22 HTML / CSS
国际礼品店:GiftsnIdeas
2018/05/03 全球购物
捷克浴室和厨房设备购物网站:SIKO
2018/08/11 全球购物
打架检讨书100字
2014/01/08 职场文书
2014年五一劳动节社区活动总结
2014/04/14 职场文书
单位租车协议书
2015/01/29 职场文书
圣诞晚会主持词开场白
2015/05/28 职场文书
nginx前后端同域名配置的方法实现
2021/03/31 Servers
详细聊聊关于Mysql联合查询的那些事儿
2021/10/24 MySQL