array.from(arr)与[...arr]的区别是什么-亚博电竞手机版

array.from(arr)与[...arr]的区别是什么?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。

类数组的特点

1.有索引

2.有长度

3.是个对象

4.能被迭代

特点说明:对于类数组的特点前三个我就不做说明了哈,主要就是最后一个,能被迭代需要具备什么呢?由图我们可以看出有一个[symbol.iterator]属性指向该对象的默认迭代器方法。那么它又是如何实现的呢?

迭代器(iterator)

作用(参考阮一峰老师的es6)

1.为各种数据结构提供一个统一的,简单的访问接口

2.使数据结构的成员能按照某种次序排序

3.供for...of循环消费

工作原理

1.创建一个指针对象,指向当前数据结构的起始位置(并且有一个next方法)

2.第一次调用对象的next方法,可以将指针指向数据结构的第一个成员

3.第二次调用对象的next方法,可以将指针指向数据结构的第二个成员

4.不断调用对象的next方法直到他指向数据结构的结束为止

注:每一次调用next方法都会返回一个包含value和done两个属性的对象,前者代表当前指针指向的数据结构成员的值,后者代表迭代是否结束

举例说明

//首先我们先创建一个待迭代的对象 letobj={0:'gu',1:'yan',2:'no.1',length:3}; console.log([...obj]);//报错uncaughttypeerror:objisnotiterable console.log(array.from(obj));//["gu","yan","no.1"] //接下来我们给待迭代对象添加一个迭代器 obj[symbol.iterator]=function(){ letindex=0; letself=this; return{ next(){ return{value:self[index],done:index  ===self.length} } } } console.log([...obj])//["gu","yan","no.1"] console.log(array.from(obj));//["gu","yan","no.1"]

通过上面的例子我相信文章前的你肯定可以懂得标题的答案了吧

虽然我们可以手动写出迭代器函数但是你不觉得很麻烦吗,所以又到了我们的另外一个知识点那就是generator生成器

generator 生成器

生成器返回的是迭代器,迭代器有next方法,调用next返回value和done

function*guyan(){  } console.log(guyan())//object[generator]{} console.log(guyan().next)//[function:next] console.loh(guyan().next())//{value:undefined,done:true}

生成器配合yield来使用如果碰到yield会暂停执行

function*guyan(){ yield1, yield2, yield3 } letit=guyan(); console.log(it.next())//{value:1,done:false} console.log(it.next())//{value:2,done:false} console.log(it.next())//{value:3,done:false} console.log(it.next())//{value:undefined,done:true}

通过生成器给obj增加迭代器

obj[symbol.iterator]=function*(){ //每次浏览器都会不停的调用next方法把yield的结果作为值 letindex=0; while(index!==this.length){ yieldthis[index  ] } } console.log([...obj])//["gu","yan","no.1"] console.log(array.from(obj));//["gu","yan","no.1"]

generatour 函数的执行顺序分析(配合图片)

function*guyan(){ leta=yield1; console.log('a',a); letb=yield2; console.log('b',b); letc=yield3; console.log('c',c); } letit=guyan(); //第一次调用it.next() it.next()//什么都没有输出 //第二次调用 it.next()//aundefined /*如果我们第二次是传入参数调用*/ it.next(100)//a100 //第三次调用 it.next(200)//b200 //第四次调用 it.next(300)//c300

当generator函数遇到promise来处理异步串行

代码示例采用node的fs模块来模拟异步

//实现前提同级目录下创建name.txtage.txt文件;name.txt中存储age.txt,age.txt中存储20 letfs=require('mz/fs');//我们直接使用mz包来实现fs的promise化 letpath=require('path'); function*guyan(){ letname=yieldfs.readfile(path.resolve(__dirname,'./name.txt'),'utf-8'); name=yield'./' name; letage=yieldfs.readfile(path.resolve(__dirname,name),'utf-8'); returnage; } letit=guyan(); let{value}=it.next(); value.then(data=>{ let{value}=it.next(data); promise.resolve(value).then(data=>{ let{value}=it.next(data) value.then(data=>{ let{value}=it.next(data); console.log(value)//20 }) }) })

对上述代码调用进行封装(实现co库)

letfs=require('mz/fs'); letpath=require('path'); function*guyan(){ letname=yieldfs.readfile(path.resolve(__dirname,'./name.txt'),'utf-8'); name=yield'./' name; letage=yieldfs.readfile(path.resolve(__dirname,name),'utf-8'); returnage; } functionco(it){ returnnewpromise((resolve,reject)=>{ functionnext(val){ let{value,done}=it.next(val); if(done){ returnresolve(value); } promise.resolve(value).then(data=>{ next(data) }) } next(); }) } co(guyan()).then(data=>{ console.log(data);//20 })

通过async await 来简化

//上述代码可以简化为 letfs=require('mz/fs'); letpath=require('path'); asyncfunctionguyan(){ letname=awaitfs.readfile(path.resolve(__dirname,'./name.txt'),'utf-8'); name='./' name; letage=awaitfs.readfile(path.resolve(__dirname,name),'utf-8'); returnage; } //async函数执行后返回一个promise //可以使用try catch,但如果使用try catch返回的就是真 guyan().then(data=>{ console.log(data); })

处理方案比较

1.callback 多个请求并发 不好管理 链式调用 导致回调嵌套过多

2.promise优点 可以优雅的处理异步 处理错误,基于回调的,还是会有嵌套问题

3.generator co 让代码像同步(比如dva)不能支持try catch

4.async await 可以是异步像同步一样处理,返回一个promise 支持try catch

看完上述内容,你们掌握array.from(arr)与[...arr]的区别是什么的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注恰卡编程网行业资讯频道,感谢各位的阅读!

展开全文
内容来源于互联网和用户投稿,文章中一旦含有亚博电竞手机版的联系方式务必识别真假,本站仅做信息展示不承担任何相关责任,如有侵权或涉及法律问题请联系亚博电竞手机版删除

最新文章

网站地图