问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

为什么javascript需要yield

发布网友 发布时间:2022-05-17 01:41

我来回答

2个回答

懂视网 时间:2022-05-17 06:02

刚才忽然灵机一动,迭代器我们很少会真的直接傻乎乎的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变得很复杂难看。所以,这个留给大家去玩吧。

热心网友 时间:2022-05-17 03:10

这玩意是从Python拉过来的,作用是合并数据集合,生成新的数据集合。
yield是一个增强版的return,可以忽略集合中不要的项,生成更小的子项;或者更改原始集合项的结构,增加项的深度。
return则是返回每一个项,如果不明确指明,这个项会被设置为undefined。
所以,yield函数里边是不能写return的,解释器不会去解释。
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
Linux系统安装FTP服务器 Linux系统的网络文件共享 建筑的七盏明灯的内容简介 面向对象设计七大原则 简单说 交互设计七大定律 交互设计的“根”——七大定律 交互设计原则和理论2——七大定律 七大设计原则 附近的加油站有哪些 附近的加油站有哪些地方 法国格勒诺布尔大学DBA难读吗? 法国格勒诺布尔大学DBA国家承认吗? 2020年法国格勒诺布尔大学DBA英文要求什么水平呢? 想报法国布雷斯特商学院DBA需要准备什么资料? 法国布雷斯特商学院的DBA怎么样? 罗丽芬芙蓉霜属于面霜吗?会不会黏腻啊? 听说罗丽芬的创始人是一个很有故事的女性? 打响爆款打一枪 淘宝直通车攻略 发电机是怎样将交流电转换成直流电的 (民熔)开关电源是怎样把交流变成直流的呢? 如何用最简单的方法把交流电转换为直流电 如何把交流24V变成直流24V 交流信号怎样变成直流信号 不用变压器,怎样将交流变直流? 智能机 能在手机QQ 上 看到对方登录的地理位置吗 在对方设置了显示的情况下 纯甄多久的保质期 我要查出对方的手机QQ在哪里登陆的?请问朋友们该怎么查? 我交通银行信用卡超过4个月未还款了,昨天收到法院通知,我害怕…… 我的信用卡额度一万三圆梦金2万逾期一年多了,说要起诉我要报案等等,心里害怕啊? 面对平安银行信用卡的催款,我很害怕,因为我现在没有钱还款,怎么办呢? 芝麻分期是骗子没办事就扣你249元? 芝麻信用借款需支付服务费是怎么回事 芝麻分贷款是分期还吗 太坑*家千万不要相信网贷先给钱的,我被快鱼分期套路过钱站套路过,芝麻分期直接坑爹! 悦木之源洗面奶尾部是F88说明保质期是多久啊? 磨砂洗面奶应多久用一次?谢谢了,大神帮忙啊 悦木之源的奇迹面膜用完是用清水洗脸还是用洗面奶洗脸? 磨砂洗面奶和普通的洗面奶有什么区别,好处? 悦木之源洗面奶适合油皮吗 用悦木之源一举两得洗面奶还需要卸妆吗 悦木之源洗面奶敏感肌肤可以用吗? 悦木之源蘑菇水,乳液,精华用的顺序 悦木之源洗面奶是氨基酸吗 悦木之源洗面奶泡沫多吗 小妇人这个电影好看吗(东方粮仓张宏伟)? 小妇人这部电影讲述的是什么? 小妇人的影片评价 yield-js 复制的全民k歌在哪里可以找到找到后又怎样发送到陌陌里面 it技术类免费的网课能学到东西吗?