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 相关文章推荐
兼容Mozilla必须知道的知识。
Jan 09 Javascript
ExtJS 2.0实用简明教程 之获得ExtJS
Apr 29 Javascript
js常用排序实现代码
Dec 28 Javascript
JS模拟面向对象全解(一、类型及传递)
Jul 13 Javascript
关于jQuery $.isNumeric vs. $.isNaN vs. isNaN
Apr 15 Javascript
AngularJS + Node.js + MongoDB开发的基于高德地图位置的通讯录
Jan 02 Javascript
利用js实现禁止复制文本信息
Jun 03 Javascript
7个去伪存真的JavaScript面试题
Jan 07 Javascript
基于javascript实现全国省市二级联动下拉选择菜单
Jan 28 Javascript
JS实现课堂随机点名和顺序点名
Mar 09 Javascript
基于JavaScript中字符串的match与replace方法(详解)
Dec 04 Javascript
vue 取出v-for循环中的index值实例
Nov 09 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 网页播放器用来播放在线视频的代码(自动判断并选择视频文件类型)
2010/06/03 PHP
PHP检测移动设备类mobile detection使用实例
2014/04/14 PHP
PHP微框架Dispatch简介
2014/06/12 PHP
详解配置 Apache 服务器支持 PHP 文件的解析
2017/02/15 PHP
php实现文件管理与基础功能操作
2017/03/21 PHP
Yii框架分页实现方法详解
2017/05/20 PHP
EXT中xtype的含义分析
2010/01/07 Javascript
js验证模型自我实现的具体方法
2013/06/21 Javascript
Ext JS 4实现带week(星期)的日期选择控件(实战二)
2013/08/21 Javascript
jquery 隐藏与显示tr标签示例代码
2014/06/06 Javascript
JavaScript中发布/订阅模式的简单实例
2014/11/05 Javascript
JavaScript SHA512&amp;SHA256加密算法详解
2015/08/11 Javascript
BootStrap 智能表单实战系列(十)自动完成组件的支持
2016/06/13 Javascript
微信小程序canvas写字板效果及实例
2017/06/15 Javascript
Vue.js常用指令的使用小结
2017/06/23 Javascript
慕课网题目之js实现抽奖系统功能
2017/09/19 Javascript
ES6 javascript中class类的get与set用法实例分析
2017/10/30 Javascript
完美解决linux下node.js全局模块找不到的情况
2018/05/16 Javascript
vue基础之data存储数据及v-for循环用法示例
2019/03/08 Javascript
Element中的Cascader(级联列表)动态加载省\市\区数据的方法
2019/03/27 Javascript
如何正确理解vue中的key详解
2019/11/02 Javascript
node静态服务器实现静态读取文件或文件夹
2019/12/03 Javascript
Python代理抓取并验证使用多线程实现
2013/05/03 Python
Python字符串特性及常用字符串方法的简单笔记
2016/01/04 Python
python找出列表中大于某个阈值的数据段示例
2019/11/24 Python
如何使用selenium和requests组合实现登录页面
2020/02/03 Python
基于Python实现人脸自动戴口罩系统
2020/02/06 Python
10个python3常用排序算法详细说明与实例(快速排序,冒泡排序,桶排序,基数排序,堆排序,希尔排序,归并排序,计数排序)
2020/03/17 Python
HTML5 3D旋转相册的实现示例
2019/12/03 HTML / CSS
英国团购网站:Groupon英国
2017/11/28 全球购物
学生打架检讨书
2014/02/14 职场文书
《在家里》教后反思
2014/03/01 职场文书
未婚证明书模板
2014/10/08 职场文书
终止劳动合同证明书样本
2014/11/19 职场文书
教师求职自荐信
2015/03/26 职场文书
golang中的struct操作
2021/11/11 Golang