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脚本实现Web页面信息交互
Dec 21 Javascript
jQuery学习笔记(4)--Jquery中获取table中某列值的具体思路
Apr 10 Javascript
javascript实现数字+字母验证码的简单实例
Feb 10 Javascript
node.js中的http.get方法使用说明
Dec 14 Javascript
JavaScript数组前面插入元素的方法
Apr 06 Javascript
javascript显示上周、上个月日期的处理方法
Feb 03 Javascript
jQuery验证插件validate使用详解
May 11 Javascript
JavaScript Base64 作为文件上传的实例代码解析
Feb 14 Javascript
如何编写jquery插件
Mar 29 jQuery
原生JavaScript实现精美的淘宝轮播图效果示例【附demo源码下载】
May 27 Javascript
Textarea输入字数限制实例(兼容iOS&amp;安卓)
Jul 06 Javascript
vue递归实现树形组件
Jul 15 Vue.js
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 pack与unpack 摸板字符字符含义
2009/10/29 PHP
php学习笔记 类的声明与对象实例化
2011/06/13 PHP
深入php self与$this的详解
2013/06/08 PHP
php使用ZipArchive提示Fatal error: Class ZipArchive not found in的解决方法
2014/11/04 PHP
Yii2简单实现给表单添加验证码的方法
2016/07/18 PHP
PHP实现简易blog的制作
2016/10/24 PHP
PHP面向对象程序设计模拟一般面向对象语言中的方法重载(overload)示例
2019/06/13 PHP
Thinkphp框架+Layui实现图片/文件上传功能分析
2020/02/07 PHP
基于json的jquery地区联动效果代码
2011/07/06 Javascript
原生js的数组除重复简单实例
2016/05/24 Javascript
AngularJs IE Compatibility 兼容老版本IE
2016/09/01 Javascript
AngularJS中isolate scope的用法分析
2016/11/22 Javascript
JavaScript定时器制作弹窗小广告
2017/02/05 Javascript
nodejs multer实现文件上传与下载
2017/05/10 NodeJs
Javascript实现基本运算器
2017/07/15 Javascript
微信小程序实现上传图片功能
2018/05/28 Javascript
angularjs http与后台交互的实现示例
2018/12/21 Javascript
从0到1搭建Element的后台框架的方法步骤
2019/04/10 Javascript
js+for循环实现字符串自动转义的代码(把后面的字符替换前面的字符)
2020/12/24 Javascript
JS相册图片抖动放大展示效果的示例代码
2021/01/29 Javascript
[43:57]Liquid vs Mineski 2019国际邀请赛小组赛 BO2 第二场 8.16
2019/08/19 DOTA
Python中强大的命令行库click入门教程
2016/12/26 Python
python实现下载整个ftp目录的方法
2017/01/17 Python
Python 元类实例解析
2018/04/04 Python
Python爬虫包BeautifulSoup异常处理(二)
2018/06/17 Python
python 使用plt画图,去除图片四周的白边方法
2019/07/09 Python
Python符号计算之实现函数极限的方法
2019/07/15 Python
python 对任意数据和曲线进行拟合并求出函数表达式的三种解决方案
2020/02/18 Python
python 爬虫请求模块requests详解
2020/12/04 Python
美赞臣营养马来西亚旗舰店:Enfagrow马来西亚
2019/07/26 全球购物
璀璨的珍珠、密钉和个性化珠宝:Lily & Roo
2021/01/21 全球购物
助人为乐表扬信范文
2014/01/14 职场文书
班组安全员工作职责
2014/02/01 职场文书
团代会宣传工作方案
2014/05/08 职场文书
社会发展项目建议书
2014/08/25 职场文书
Python安装使用Scrapy框架
2022/04/12 Python