举例说明iterator迭代器接口的使用方法,javascript generator
本文已经给大家带来了一些关于JavaScript的知识,主要介绍JavaScript的前端迭代器和生成器。有需要的朋友可以参考一下,希望能有所帮助。
【相关推荐:javascript视频教程,web前端】
Iterator 概念
迭代器提供统一的接口机制,为各种不同的数据结构提供统一的访问机制。
定义迭代器就是用next()方法提供一个对象。每次调用next()时,都会返回一个结果对象。结果对象有两个属性,value表示当前值,done表示遍历是否完成。
函数makeIterator(数组){
设索引=0;
返回{
下一个:function(){
返回(
数组.长度索引?
{值:数组[索引]}:
{完成:正确}
)
}
}
}
let iterator=makeIterator([1 , 2])
console . log(iterator . next());//{值: 1}
console . log(iterator . next());//{值: 2}
console . log(iterator . next());//{done: true}迭代器的作用:
为各种数据结构提供统一简单的访问接口;以便数据结构的成员可以按一定的顺序排列;为.of消费
默认 Iterator 接口
ES6提供了for of语句来遍历迭代器对象。让我们使用for of语句来遍历上面创建的迭代器:
let iterator=makeIterator([1 , 2])
for(让迭代器的值){
console.log(值);
} //迭代器不可迭代。结果报告了一个错误,指出迭代器不可迭代。这是为什么呢?ES6规定默认迭代器接口部署在数据结构的Symbol.iterator属性中。如果数据结构具有Symbol.iterator属性,则可以遍历该数据结构。
我们将自定义makeIterator转换如下:
const MakeIterator=(Array)=({
[Symbol.iterator](){
设索引=0;
返回{
下一个(){
let length=Array.length
if(索引长度){
返回{value: Array[index ]}
}否则{
返回{done: true}
}
}
}
}
})
for(让MakeIterator的值([1,2]){
console.log(值)
}
//1
//2
Iterator 的 return()
我们为MakeIterator添加返回方法。如果的.of循环提前退出(通常是因为错误或break语句),将调用return()方法来终止遍历。
基于这个特性,如果一个对象在完成遍历之前需要清理或释放资源,我们可以部署return()方法,包括在文件读取失败时关闭文件。
const MakeIterator=(Array)=({
[Symbol.iterator](){
设索引=0;
返回{
下一个(){
let length=Array.length
if(索引长度){
返回{value: Array[index ]}
}否则{
返回{done: true}
}
},
return()
返回{done: true}
}
}
}
})
for(让MakeIterator的值([1,2,3]){
console.log(value) //1
//模式1
打破;
//模式2
//抛出新错误( Error );
}
原生具备 Iterator 接口的数据结构
array SetMap类数组对象,如arguments对象、DOM NodeList对象、typedArray对象//arguments对象。
函数sum(){
for(让参数值){
console.log(值)
}
}
sum(1,2)
//1
//2
//typedArray对象
设type arry=new int 8 array(2);
type arry[0]=1;
type arry[1]=2;
for(让typeArry的值){
console.log(值)
}
//1
//2生成器对象函数* gen(){
产量1;
产量2;
}
for(let值为gen()){
console.log(值)
}StringQ:为什么Object没有原生迭代器?
答:对象默认不部署迭代器接口的原因是不确定先遍历对象的哪个属性,后遍历哪个属性。
本质上,遍历是一个线性过程。对于任何非线性数据结构,部署遍历接口相当于部署线性转换。
但是严格来说,并不需要为对象部署遍历接口,因为对象实际上是作为一个Map结构使用的,ES5没有Map结构,但是ES6原生提供了。
调用 Iterator 接口的场合
解构分配字母set=newset()。添加( a )。添加( b )。add( c );
设[x,y]=set;//x= a ;Y=b 扩展运算符var str= hello
[.str]//[h , e , l , l , o]扩展运算符是调用迭代器接口,所以Object不部署迭代器接口。为什么它也可以使用.接线员?
原因:扩展运算符有两种。
一个用于函数参数和数组扩展时,要求对象可迭代,另一个用于对象扩展,即{…obj} form,要求对象可枚举)让obj1={
姓名:“钱逊”
}
设obj2={
年龄:3岁
}
//数组对象是可枚举的
让obj={.obj1,obj2}
console . log(obj)//{姓名:钱逊,年龄:3}
//默认情况下,普通对象是非迭代的
让obj=[.obj1,obj2]
console.log(obj) //对象不可迭代
模拟实现 for of
of(obj,cb){
let iterator value=obj[symbol . iterator]();
let result=iteratorValue.next()
而(!result.done){
cb(结果值)
result=iteratorValue.next()
}
}
forOf([1,2,3],(值)={
console.log(值)
})
//1
//2
//3
Generator
认识 Generator
概念上,生成器函数是ES6提供的异步编程解决方案。生成器函数是一个状态机,它封装了多个内部状态。
生成器函数也是一个遍历对象生成函数,执行后返回一个遍历对象。
form 1.function关键字和函数名之间有一个星号;
2.在函数体内使用yield表达式来定义不同的内部状态。
函数* simpleGenerator(){
产量1;
产量2;
}
SimpleGenerator()如上所述,我们创建了一个简单的生成器,并用两个问题对其进行了探索:
生成器函数运行后会发生什么?函数中yield表达式的作用是什么?函数* simpleGenerator(){
console . log( hello world );
产量1;
产量2;
}
let generator=simple generator();//simple generator { lt;已暂停}}
console.log(generator.next())
//你好世界
//{值:1,完成:假}
console.log(generator.next())
//{value: 2,done: false}生成器函数运行后返回一个生成器对象,而普通函数会直接执行函数内部的代码;每次调用generator对象的next方法,都会执行该函数,直到下一次yield关键字停止执行,并返回一个{value: Value,done: Boolean}对象。
next 方法的参数
yield表达式本身没有返回值,或者总是返回undefined。下一个方法可以接受一个参数,该参数将作为前面yield表达式的返回值。通过next方法的参数,可以在生成器函数的不同阶段从外到内注入不同的值,从而调整函数行为。由于next方法的参数代表前一个yield表达式的返回值,所以第一次使用next方法时,传递的参数无效。
函数sum(x){
返回函数(y){
返回x y;
}
}
console.log(sum(1)(2))
//用下一个参数重写。
函数* sum(x){
设y=产量x;
while(true){
y=产量x y;
}
}
设gen=sum(2)
console.log(gen.next()) //2
console.log(gen.next(1)) //3
console . log(gen . next(2))//4
yield 表达式
yield表达式的作用:定义内部状态,暂停yield表达式的执行,与return语句不同。
产量表达式表示函数暂停执行,下一次再从该位置继续向后执行,而返回语句不具备位置记忆的功能一个函数里,只能执行一个返回语句,但是可以执行多个产量表达式任何函数都可以使用返回语句,产量表达式只能用在发电机函数里面,用在其他地方都会报错产量表达式如果参与运算放在圆括号里面;用作函数参数或放在赋值表达式的右边,可以不加括号函数*gen () {
console.log(hello yield)
console.log(hello (yield))
console.log(hello 产量1)
console.log(hello (yield 1))
foo(收益率1)
常量参数=产量2
}基于发电机生成器函数中可以支持多个产量,我们可以实现一个函数有多个返回值的场景:
函数* gen(num1,num2){
产出数字1数字2
产量num 1-num 2;
}
设res=gen(2,1);
控制台。log(RES . next())//{ value:3,done: false}
控制台。log(RES . next())//{ value:1,done: false}
Generator 与 Iterator 之间的关系
由于发电机函数就是遍历器生成函数,因此可以把发电机赋值给对象的符号迭代器属性,从而使得该对象具有迭代程序接口发电机。实现方式代码更加简洁。
让obj={
姓名:"钱逊",
年龄:3岁,
[Symbol.iterator]:函数(){
让那个=这个;
let keys=Object.keys(that)
设索引=0;
返回{
下一个:函数(){
返回索引键,长度?
{value: that[keys[index ]],done: false}:
{值:未定义,完成:真}
}
}
}
}
对于(对象的字母值){
console.log(值)
}发电机:
让obj={
姓名:"钱逊",
年龄:3岁,
[Symbol.iterator]:函数*(1)
let keys=Object.keys(this)
对于(设I=0;I key . length I){
产生这个[keys[I]];
}
}
}
对于(对象的字母值){
console.log(值)
}
Generator.prototype.return()
函数* gen() {
产量1;
产量2;
产量3;
}
var g=gen();
g.next() //{ value: 1,done: false }
//如果return()方法调用时,不提供参数,则返回值的价值属性为不明确的
g.return(foo) //{ value: foo ,done: true }
g.next() //{ value: undefined,done: true }如果发电机函数内部有尝试.最后代码块,且正在执行尝试代码块,那么return()方法会导致立刻进入最后代码块,执行完以后,整个函数才会结束。
函数*数字(){
产量1;
尝试{
产量2;
产量3;
}最后{
产量4;
产量5;
}
产量6;
}
var g=numbers();
g.next() //{ value: 1,done: false }
g.next() //{ value: 2,done: false }
g.return(7) //{ value: 4,done: false }
g.next() //{ value: 5,done: false }
g.next() //{ value: 7,done: true }
yield* 表达式
如果想在发电机函数内部,调用另一个发电机函数。我们需要在前者的函数体内部,自己手动完成遍历,如果函数调用多层嵌套会导致写法繁琐不易阅读,ES6提供了产量*表达式作为解决方法。
委托给其他生成器
函数* g1() {
产量2;
产量3;
}
函数* g2() {
产量1;
产量* G1();
产量4;
}
常数迭代器=G2();
控制台。log(迭代器。next());//{值:1,完成:假}
控制台。log(迭代器。next());//{ value: 2,done: false }
控制台。log(迭代器。next());//{值:3,完成:假}
控制台。log(迭代器。next());//{ value: 4,done: false }
控制台。log(迭代器。next());//{值:未定义,完成:真}委托给其他可迭代对象
函数* gen(){
收益率* [1,2,3]
}
console.log(gen().next()) //{value: 1,done: false}
Generator 函数的 this
生成器函数返回一个遍历器,ES6规定这个遍历器是发电机函数的实例,继承了发电机。原型对象上的方法,但无法获取这上的属性,因为这时这是全局对象,而不是实例对象。
函数* gen(){
this.a=1
}
gen.prototype.say=function(){
console.log(hi )
}
让obj=gen()
控制台。log(生成的对象实例)//true
你好
obj.next()
控制台。日志(对象。a)//未定义如果想像构造函数一样访问实例属性,可以修改这绑定到发电机。原型上。
函数* gen(){
this.a=1
}
gen.prototype.say=function(){
console.log(hi )
}
let obj=gen.call(gen.prototype)
控制台。log(生成的对象实例)//true
你好
obj.next()
console.log(obj.a) //1
Generator 实现一个状态机
函数*状态机(state){
让过渡;
while(true){
if(transition===INCREMENT){
状态;
} else if(transition=== DECREMENT ){
状态-;
}
转变=屈服状态;
}
}
常数迭代器=状态机(0);
控制台。log(迭代器。next());//0
控制台。log(迭代器。next( INCREMENT ));//1
控制台。log(迭代器。下一个(减量);//0【相关推荐:javascript视频教程、网络前端】以上就是Java脚本语言前端迭代器迭代程序与生成器发电机讲解的详细内容,更多请关注我们其它相关文章!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。