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 相关文章推荐
js实现的map方法示例代码
Jan 13 Javascript
使用focus方法让光标默认停留在INPUT框
Jul 29 Javascript
javascript实现百度地图鼠标滑动事件显示、隐藏
Apr 02 Javascript
javascript实现标签切换代码示例
May 22 Javascript
js利用正则表达式检验输入内容是否为网址
Jul 05 Javascript
基于jQuery实现照片墙自动播放特效
Jan 12 Javascript
微信小程序 两种滑动方式(横向滑动,竖向滑动)详细及实例代码
Jan 13 Javascript
vue实现图片加载完成前的loading组件方法
Feb 05 Javascript
vue嵌套路由与404重定向实现方法分析
May 04 Javascript
JS深入学习之数组对象排序操作示例
May 01 Javascript
jdk1.8+vue elementui实现多级菜单功能
Sep 24 Javascript
比较node.js和Deno
Apr 27 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
Codeigniter出现错误提示Error with CACHE directory的解决方案
2014/06/12 PHP
深入分析PHP引用(&amp;)
2014/09/04 PHP
初识php MVC
2014/09/10 PHP
PHP入门教程之自定义函数用法详解(创建,调用,变量,参数,返回值等)
2016/09/11 PHP
Yii2语言国际化自动配置详解
2018/08/22 PHP
thinkphp5.1框架模板布局与模板继承用法分析
2019/07/19 PHP
php写入mysql中文乱码的实例解决方法
2019/09/17 PHP
PHPStorm 2020.1 调试 Nodejs的多种方法详解
2020/09/17 NodeJs
ie下jquery.getJSON的缓存问题的处理方法
2013/03/29 Javascript
Javascript实现带关闭按钮的网页漂浮广告代码
2014/01/12 Javascript
jQuery实现列表的全选功能
2015/03/18 Javascript
javascript实现判断鼠标的状态
2015/07/10 Javascript
一览画面点击复选框后获取多个id值的方法
2016/05/30 Javascript
第一次动手实现bootstrap table分页效果
2016/09/22 Javascript
详解微信小程序 页面跳转 传递参数
2016/12/08 Javascript
JS基于正则实现数字千分位用逗号分隔的方法
2017/06/16 Javascript
Vue单页应用引用单独的样式文件的两种方式
2018/03/30 Javascript
JavaScript之实现一个简单的Vue示例
2019/01/17 Javascript
js实现随机数小游戏
2019/06/28 Javascript
localstorage实现带过期时间的缓存功能
2019/06/28 Javascript
在Python中处理字符串之isdecimal()方法的使用
2015/05/20 Python
python实现爬虫统计学校BBS男女比例(一)
2015/12/31 Python
python实现八大排序算法(2)
2017/09/14 Python
python使用PyQt5的简单方法
2019/02/27 Python
python 在某.py文件中调用其他.py内的函数的方法
2019/06/25 Python
python暴力解压rar加密文件过程详解
2019/07/05 Python
利用Python库Scapy解析pcap文件的方法
2019/07/23 Python
关于python pycharm中输出的内容不全的解决办法
2020/01/10 Python
python实现图片横向和纵向拼接
2020/03/05 Python
Baracuta官方网站:Harrington夹克,G9,G4,G10等
2018/03/06 全球购物
文科教师毕业的自我评价
2014/01/16 职场文书
2014年小学工作总结
2014/11/26 职场文书
学校捐款活动总结
2015/05/09 职场文书
药房管理制度范本
2015/08/06 职场文书
Matlab如何实现矩阵复制扩充
2021/06/02 Python
python和C/C++混合编程之使用ctypes调用 C/C++的dll
2022/04/29 Python