扣丁学堂HTML5培训之谈谈ES6语法(汇总中篇)

2019-07-23 17:16:20 2881浏览

关于ES6语法扣丁学堂HTML5培训小编已经给大家分享过一篇文章了,那就是《扣丁学堂HTML5培训之谈谈ES6语法(汇总上篇)》本篇文章小编接着给大家分享关于ES6语法的知识,下面就随小编一起来看一下吧。


扣丁学堂HTML5培训之谈谈ES6语法(汇总中篇)


数组扩展


数组扩展运算符


数组扩展运算符(spread)是三个点(...)。它好比rest参数的逆运算,将一个数组转为用空格分隔的参数序列。


console.log(...[1,2,3]);//123
console.log(1,...[2,3,4],5);//12345

rest参数是运用在函数参数上的,将函数参数转换为数组的形式,如下:



functionfn(...values){
console.log(values);//['jia','ming']
}
fn('jia','ming');

下面我们结合数组扩展运算符和rest参数来实现一个类似call的方法call2操作:



Function.prototype.call2=function(context,...args){//这里使用到rest参数
context=context||window;//因为传递过来的context有可能是null
context.fn=this;//让fn的上下文为context
constresult=context.fn(...args);//这里使用了数组扩展运算符
deletecontext.fn;
returnresult;//因为有可能this函数会有返回值return
}
varjob='outterteacher';
varobj={
job:'innerteacher'
};
functionshowJob(){
console.log(this.job);
}
showJob();//outterteacher
showJob.call2(obj);//innerteacher


复习一下,我们把varjob='outterteacher'改为letjob='outterteacher'后,showJob()会输出什么?



答案是undefined。在前一篇中也提到过,ES6语法声明的变量是不会挂载在全局对象上的~


Array.from()



Array.from方法用于将两类对象转为真正的数组:类似数组的对象(array-likeobject)和可遍历(iterable)的对象(对象包括ES6新增的数据结构Set和Map)。


//类数组转化成数组
letarrayLike={
'0':'a',
'1':'b',
'2':'c',
length:3
}

//ES5的写法
vararr1=[].slice.call(arrayLike);//['a','b','c']

//ES6的写法
letarr2=Array.from(arrayLike);//['a','b','c']


Array.of()



Array.of()方法用于将一组值,转换为数组。


letarr=Array.of(2,3,'reng');
console.log(arr);//[2,3,'reng']
console.log(arr.pop());//reng

Array.of基本上可以弥补Array()或newArray()带来的因为参数个数导致的不同行为。Array.of基本上可以替代它们两个了。



Array.of();//[]
Array.of('reng');//['reng']
Array.of(2,'reng');//[2,'reng']


数组中还有其它有用的方法:



copyWithin(target,start=0,end=this.length):拷贝指定数组的范围值
find(fn):用于查找第一个符合条件的数组成员,没有返回undefined
findIndex(fn):用于查找第一个符合条件的数组成员的位置,没有返回-1
entries():对键值对的遍历
keys():对键的遍历
values():对值的遍历
includes(el):返回一个布尔值,表示某个数组是否包含给定的值,与字符串的include(el)方法相似
flat(num):将嵌套的数组拉平,num是遍历的深度


[1,[2,[3]]].flat(Infinity);
//[1,2,3]


有这么一个需求:将数组[[2,8],[2],[[4,6],7,6]]转成一维且元素不重复的数组。
我们的实现方案如下:



letarr=[[2,8],[2],[[4,6],7,6]];
console.log([...newSet(arr.flat(Infinity))]);//[2,8,4,6,7]



对象扩展


属性名表达式


ES6允许字面量定义对象时,把表达式放在方括号内:


letlastWord='lastword';

consta={
'firstword':'hello',
[lastWord]:'world',
['end'+'symbol']:'!'
};

a['firstword']//'hello'
a[lastWord]//'world'
a['lastword']//'world'
a['endsymbol']//'!'


对象的扩展运算符



上面整理数组扩展内容的时候,提到了数组的扩展运算符。ES2018将这个运算符引入了对象~


letz={a:3,b:4};
letn={...z};//关键点
n//{a:3,b:4}

对象中某些新增的方法



Object.is(arg1,arg2):比较两个值是否严格相等,与===行为基本一致
Object.assign(target,source1,...):用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。属于浅拷贝
Object.keys(obj):返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键名
Object.values(obj):方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值。
Object.entries(obj):方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值对数组。


constobj={foo:'bar',baz:42};
Object.entries(obj)
//[["foo","bar"],["baz",42]]


Set和Map数据结构


Set


Set翻译出来就是集合,有元素唯一性的特点。


在数组去重的场景上很有用处:


//去除数组的重复成员
[...newSet(array)]
//如
console.log([...newSet([2,2,3,2])]);//[2,3]

需要留意的Set属性和方法有以下:



size:返回实例成员的总数
add(value):添加某个值,返回Set结构本身
delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
has(value):返回一个布尔值,表示该值是否为Set的成员
clear():清除所有成员,没有返回值。
key():返回键名的遍历器。
values():返回键值的遍历器。
entries():返回键值对的遍历器。
forEach():使用回调函数遍历每个成员


WeakSet


WeakSet结构与Set类似,也是有不重复元素的集合。但是它和Set有两个区别:


WeakSet对象中只能存放对象引用,不能存放值,而Set对象都可以.
WeakSet中对象中存储的对象值都是被弱引用的,如果没有其他的变量或属性引用这个对象值,则这个对象值会被当成垃圾回收掉.正因为这样,WeakSet对象是无法被枚举的,没有办法拿到它包含的所有元素。


varws=newWeakSet();
varobj={};
varfoo={};

ws.add(window);
ws.add(obj);

ws.has(window);//true
ws.has(foo);//false,对象foo并没有被添加进ws中

ws.delete(window);//从集合中删除window对象
ws.has(window);//false,window对象已经被删除了

ws.clear();//清空整个WeakSet对象

WeakSet没有size属性,没有办法遍历它的成员。

Map



Map对象保持键值对。任何值(对象或者原始值)都可以作为一个键或一个值。



Object和Map的比较:

一个Object的键只能是字符串或者Symbols,但一个Map的键可以是任意值,包括函数、对象、基本类型。


Map中的键值是有序的,而添加到对象中的键则不是。因此,当对它进行遍历时,Map对象是按插入的顺序返回键值。


Map在涉及频繁增删键值对的场景下会有些性能优势`。


...


如果你需要“键值对”的数据结构,Map比Object更合适。


constset=newSet([//数组转换为map
['foo',1],
['bar',2]
]);
constm1=newMap(set);
m1.get('foo')//1

constm2=newMap([['baz',3]]);
constm3=newMap(m2);
m3.get('baz')//3


Map拥有的属性和方法和Set相似,多出了些:



set(key,value):set方法设置键名key对应的键值为value,然后返回整个Map结构。如果key已经有值,则键值会被更新,否则就新生成该键。
get(key):get方法读取key对应的键值,如果找不到key,返回undefined


WeakMap


WeakMap结构与Map结构类似,也是用于生成键值对的集合。但是有两点区别:


WeakMap只接受对象作为键名(null除外),不接受其他类型的值作为键名。
WeakMap的键名所指向的对象,不计入垃圾回收机制。和WeakSet相似啦。
属性方法啥的跟Map差不多,就是没有了size和forEach,因为其是不可枚举的。



Promise对象


Promise是异步编程的一种解决方案,比传统的解决方案“回调函数和事件”更合理和更强大。
Promise对象有以下两个特点:


对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。


一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种情况:从pending变成fulfilled(fulfilled也称resolved)和从pending变成rejected。



用法


constpromise=newPromise(function(resolve,reject){
//...somecode

if(/*异步操作成功*/){
resolve(value);
}else{
reject(error);
}
})

参数resolve和reject是两个函数,由JavaScript引擎提供,不用自己部署。


Promise实例生成之后,可以使用then方法分别指定resolved状态和rejected状态的回调函数。


promise.then(function(value){
//success
},function(error){
//failure
});

我们来粘贴个简单例子:



functiontimeout(ms){
returnnewPromise((resolve,reject)=>{
setTimeout(resolve,ms,'done');
});
}

timeout(100).then((value)=>{
console.log(value);//100ms后输出'done'
});


嗯~我们顺道来复习下setTimeout的第四个参数。



vartimeoutID=scope.setTimeout(function[,delay,param1,param2,...]);

function是你想要在到期时间(delay毫秒)之后执行的函数。
delay是可选语法,表示延迟的毫秒数。
param1,...,paramN是可选的附加参数,一旦定时器到期,它们会作为参数传递给function



那么,到这里你理解了上面的例子为什么在100ms后输出done了嘛?



简单的例子看完了,看下我们在工作中使用得比较多的请求接口的例子:


constgetJSON=function(url){
constpromise=newPromise(function(resolve,reject){
consthandler=function(){
if(this.readyState!==4){
return;
}
if(this.status===200){
resolve(this.response);//this.response作为参数传给then中的json
}else{
reject(newError(this.statusText));
}
};
constclient=newXMLHttpRequest();
client.open('GET',url);
client.onreadystatechange=handler;
client.responseType='json';
client.setRequestHeader('Accept','application.json');
client.send();
});
returnpromise;
};
getJSON('/post.json').then(function(json){
console.log('Contents:'+json);
},function(error){
console.log('errorhappen',error);
});


catch方法



Promise.prototype.catch方法是.then(null,rejection)或.then(undefined,rejection)的别名,用于指定发生错误时的回调函数。p.then((val)=>console.log('fulfilled:',val))
.catch((err)=>console.log('rejected',err));//promise中任何一个抛出错误,都会被最后一个catch捕获

//等同于
p.then((val)=>console.log('fulfilled:',val))
.then(null,(err)=>console.log('rejected:',err));


finally方法



Promise.prototype.finally()方法(其不接受任何参数)用于指定不管Promise对象最后状态如何,都会执行的操作。该方法是ES2018引入标准的。
语法:promise
.then(result=>{···})
.catch(error=>{···})
.finally(()=>{···});


Promise.all



构造函数方法Promise.all方法用于将多个Promise实例,包装成一个新的Promise实例。


constp=Promise.all([p1,p2,p3]);

上面代码中,Promise.all方法接受一个数组作为参数,p1,p2,p3都是Promise实例。如果不是会调用Promise.resolve方法。



//生成一个Promise对象的数组
constpromises=[2,3,5,7,11,13].map(function(id){
returngetJSON('/post/'+id+".json");
});

Promise.all(promises).then(function(posts){
//...
}).catch(function(reason){
//...
});


上面代码中,promises是包含6个Promise实例的数组,只有这6个实例的状态都变成fulfilled,或者其中有一个变为rejected,才会调用Promise.all方法后面的回调函数。




注意,如果作为参数的Promise实例,自己定义了catch方法,那么它一旦被rejected,并不会触发Promise.all()的catch方法。所以使用Promise.all()别手痒在每个实例promise内添加错误捕获。


一道练手题


需求:使用promise改写下面的代码,使得输出的期望结果是每隔一秒输出0,1,2,3,4,5,其中i<5条件不能变


for(vari=0;i<5;i++){
setTimeout(function(){
console.log(i);
},1000)
}
console.log(i);

我们直接上使用promise改写的代码吧~



consttasks=[];//存放promise对象
for(leti=0;i<5;i++){
tasks.push(newPromise((resolve)=>{
setTimeout(()=>{
console.log(i);
resolve();
},1000*i);
}));
}
Promise.all(tasks).then(()=>{
setTimeout(()=>{
console.log(tasks.length);
},1000);
});
//每隔一秒输出0,1,2,3,4,5


想要了解更多关于HTML5开发方面内容的小伙伴,请关注扣丁学堂HTML5培训官网、微信等平台,扣丁学堂IT职业在线学习教育有专业的HTML5讲师为您指导,此外扣丁学堂老师精心推出的HTML5视频教程定能让你快速掌握HTML5从入门到精通开发实战技能。扣丁学堂H5技术交流群:673883249。



                           【扫码进入HTML5VIP免费公开课】  


     【关注微信公众号获取更多学习资料】        【扫码进入HTML5前端开发VIP免费公开课】  



查看更多关于“HTML5开发技术资讯”的相关文章>>



标签: HTML5培训 HTML5视频教程 HTML5学习视频 HTML5在线视频 HTML5培训班 微信小程序

热门专区

暂无热门资讯

课程推荐

微信
微博
15311698296

全国免费咨询热线

邮箱:codingke@1000phone.com

官方群:148715490

北京千锋互联科技有限公司版权所有   北京市海淀区宝盛北里西区28号中关村智诚科创大厦4层
京ICP备12003911号-6   Copyright © 2013 - 2019

京公网安备 11010802030908号