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 相关文章推荐
破除一些网站复制、右键限制
Nov 04 Javascript
JS关键字变色实现思路及代码
Feb 21 Javascript
浅析JQuery UI Dialog的样式设置问题
Dec 18 Javascript
jquery改变tr背景色的示例代码
Dec 28 Javascript
9款2014最热门jQuery实用特效推荐
Dec 07 Javascript
JavaScript中的this到底是什么(一)
Dec 09 Javascript
一个简单的JavaScript Map实例(分享)
Aug 03 Javascript
详解JavaScript权威指南之对象
Sep 27 Javascript
js实现固定宽高滑动轮播图效果
Jan 13 Javascript
jQuery学习之DOM节点的插入方法总结
Jan 22 Javascript
详解AngularJs ui-router 路由的简单介绍
Apr 26 Javascript
vue+element模态框中新增模态框和删除功能
Jun 11 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横向重复区域显示二法
2008/09/25 PHP
JoshChen_web格式编码UTF8-无BOM的小细节分析
2013/08/16 PHP
ThinkPHP之foreach标签使用概述
2014/06/30 PHP
php字符串截取函数mb_substr用法实例分析
2019/06/25 PHP
添加到收藏夹代码(兼容几乎所有的浏览器)
2007/01/09 Javascript
用Javascript读取中文COOKIE的解决办法
2007/02/15 Javascript
JQUERY设置IFRAME的SRC值的代码
2010/11/30 Javascript
为原生js Array增加each方法
2012/04/07 Javascript
JavaScript中数组对象的那些自带方法介绍
2013/03/12 Javascript
JavaScript设置IFrame高度自适应(兼容各主流浏览器)
2013/06/05 Javascript
iframe的onreadystatechange事件在firefox下的使用
2014/04/16 Javascript
JS使用parseInt解析数字实现求和的方法
2015/08/05 Javascript
JavaScript实现打印星型金字塔功能实例分析
2017/09/27 Javascript
vue和react等项目中更简单的实现展开收起更多等效果示例
2018/02/22 Javascript
js传递数组参数到后台controller的方法
2018/03/29 Javascript
100行代码实现一个vue分页组功能
2018/11/06 Javascript
Vue组件教程之Toast(Vue.extend 方式)详解
2019/01/27 Javascript
详解如何在Vue项目中导出Excel
2019/04/19 Javascript
通过实践编写优雅的JavaScript代码
2019/05/30 Javascript
ES6中字符串的使用方法扩展
2019/06/04 Javascript
layui实现数据表格table分页功能(ajax异步)
2019/07/27 Javascript
Vue前端判断数据对象是否为空的实例
2020/09/02 Javascript
[10:39]DOTA2上海特级锦标赛音乐会纪录片
2016/03/21 DOTA
Python import用法以及与from...import的区别
2015/05/28 Python
Python选课系统开发程序
2016/09/02 Python
Python使用sorted排序的方法小结
2017/07/28 Python
解决Django模板无法使用perms变量问题的方法
2017/09/10 Python
scrapy爬虫完整实例
2018/01/25 Python
python上下文管理的使用场景实例讲解
2021/03/03 Python
Bluebella美国官网:英国性感内衣品牌
2018/10/04 全球购物
成人大专自我鉴定范文
2013/10/19 职场文书
卫生安全检查制度
2014/02/04 职场文书
超市开学活动方案
2014/03/01 职场文书
后进基层党组织整改方案
2014/10/25 职场文书
学生个人评语大全
2015/01/04 职场文书
详解PHP设计模式之依赖注入模式
2021/05/25 PHP