今天扣丁学堂HTML5培训小编给读者们分享关于ES6语法总结的最后一篇,那就是谈谈ES6语法(汇总下篇),废话就不多说了,我们就直接开始吧。
async函数
ES2017标准引入了async函数,使得异步操作更加方便。async函数是Generator函数的语法糖。不打算写Generator函数,感兴趣的话可以看文档。与Generator返回值(Iterator对象)不同,async返回的是一个Promise对象。
用法
async函数返回一个Promise对象,可以使用then方法添加回调函数。当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。
asyncfunctiongetStockPriceByName(name){
constsymbol=awaitgetStockSymbol(name);
conststockPrice=awaitgetStockPrice(symbol);
returnstockPrice;
}
getStockPriceByName('goog').then(function(result){
console.log(result);
})
再来看几种情况加深下印象:
functionfun1(){
console.log('fun1');
return'fun1result';
}
asyncfunctiontest(){
constresult1=awaitfun1();
console.log(result1);
console.log('end');
}
test();
//输出
//'fun1'
//'fun1result'
//'end'
asyncfunctionfun2(){
console.log('fun2');
return'fun2result';
}
asyncfunctiontest(){
constresult2=awaitfun2();
console.log(result2);
console.log('end');
}
test();
//输出
//'fun2'
//'fun2result'
//'end'
正常情况下,await命令后面是一个Promise对象,返回该对象的结果。如果不是Promise对象,就直接返回对应的值。
asyncfunctionfun3(){
console.log('fun3');
setTimeout(function(){
console.log('fun3async');
return'fun3result';
},1000)
}
asyncfunctiontest(){
constresult3=awaitfun3();
console.log(result3);
console.log('end');
}
test();
//输出
//'fun3'
//undefined
//'end'
//'fun3async'
asyncfunctionfun4(){
console.log('fun4');
returnnewPromise((resolve,reject)=>{
setTimeout(()=>{
console.log('fun4async');
resolve('fun4result');
},1000);
})
}
asyncfunctiontest(){
console.log(result4);
console.log('fun4sync');
console.log('end');
}
test();
//输出
//'fun4'
//'fun4async'
//'fun4result'
//'fun4sync'
//'end'
模拟sleep
JavaScript一直没有休眠的语法,但是借助await命令就可以让程序停顿指定的时间。【await要配合async来实现】
functionsleep(interval){
returnnewPromise(resolve=>{
setTimeout(resolve,interval);
})
}
//use
asyncfunctionone2FiveInAsync(){
for(leti=1;i<=5;i++){
console.log(i);
awaitsleep(1000);
}
}
one2FiveInAsync();
//1,2,3,4,5每隔一秒输出数字
一道题
需求:使用asyncawait改写下面的代码,使得输出的期望结果是每隔一秒输出0,1,2,3,4,5,其中i<5条件不能变。
for(vari=0;i<5;i++){
setTimeout(function(){
console.log(i);
},1000)
}
console.log(i);
我们用asyncawait方式来实现:
constsleep=(time)=>newPromise((resolve)=>{
setTimeout(resolve,time);
});
(async()=>{
for(vari=0;i<5;i++){
console.log(i);
awaitsleep(1000);
}
console.log(i);
})();
//符合条件的输出0,1,2,3,4,5
比较promise和async
为什么只比较promise和async呢?因为最近用得频繁,实在的才是需要的,而且async语法是generator的语法糖。
两者上,async语法写法上代码量少,错误处理能力佳,而且更有逻辑语义化。
假定某个DOM元素上面,部署了一系列的动画,前一个动画结束,才能开始后一个。如果当中有一个动画出错,就不再往下执行,返回上一个成功执行的动画的返回值。
//promise
functionchainAnimationsPromise(elem,animations){
//变量ret用来保存上一个动画的返回值
letret=null;
//新建一个空的Promise
letp=Promise.resolve();
//使用then方法,添加所有动画
for(letanimofanimations){
p=p.then(function(val){
ret=val;
returnanim(elem);
});
}
//返回一个部署了错误捕捉机制的Promise
returnp.catch(function(e){
/*忽略错误,继续执行*/
}).then(function(){
returnret;
});
}
//asyncawait
asyncfunctionchainAnimationsAsync(elem,animations){
letret=null;
try{
for(letanimofanimations){
ret=awaitanim(elem);
}
}catch(e){
/*忽略错误,继续执行*/
}
returnret;
}
类class
在ES6之前,是使用构造函数来模拟类的,现在有了关键字class了,甚是开心??
functionPerson(){}
Person.prototype.sayHello=function(){
console.log('Hi');
};
classPerson{
sayHello(){
console.log('Hi!');
}
}
constructor方法
constructor方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法,一个类中必须有construtor方法,如果没有显式定义,一个空的constructor方法会默认添加。
classPerson{}
//等同于
classPerson{
constructor(){}
}
construtor方法也就类似构造函数,在执行new的时候,先跑构造函数,再跑到原型对象上。
取值函数(getter)和存值函数(setter)
与ES5一样,在类的内部可以使用get和set关键字,对某个属性设置存值函数和取值函数,拦截该属性的存取行为。
classMyClass{
getprop(){
return'getter';
}
setprop(value){
console.log(`setter:${value}`)
}
}
letinst=newMyClass();
inst.prop=123;
//'setter:123'
console.log(inst.prop);
//'getter'
this的指向
类的方法内部如果含有this,它默认是指向类的实例。但是,必须非常小心,一旦单独使用该方法,很可能报错。
classPerson{
constructor(job){
this.job=job;
}
printJob(){
console.log(`Myjobis${this.job}`);
}
sayHi(){
console.log(`Ilovemyjob--${this.job}.`)
}
}
constperson=newPerson('teacher');
person.printJob();//'Myjobisteacher'
const{sayHi}=person;
sayHi();//报错:UncaughtTypeError:Cannotreadproperty'job'ofundefined
上面的代码中,sayHi方法单独使用,this会指向该方法运行时所在的环境(由于class内部是严格模式,所以this实际上指向undefined)。
修正上面的错误也很简单,也是我们在react开发中经常使用的一种手段:在调用构造函数实例化的时候直接绑定实例(this),修改如下:
classPerson{
constructor(job){
this.job=job;
this.sayHi=this.sayHi.bind(this);
}
}
继承
ES6中的继承通过extends关键字实现,比ES5的实现继承更加清晰和方便了。
classPoint{
constructor(x,y){
this.x=x;
this.y=y;
}
}
classColorPointextendsPoint{
constructor(x,y,color){
this.color=color;
}
}
letcp=newColorPoint(25,8,'green');//报错:Mustcallsuperconstructorinderivedclassbeforeaccessing'this'orreturningfromderivedconstructor
上面这样写,不能继承构造函数里面的属性值和方法。需要在子类的构造函数中加上super关键字。改成下面这样即可:
classPoint{
constructor(x,y){
this.x=x;
this.y=y;
}
}
classColorPointextendsPoint{
constructor(x,y,color){
super(x,y);//调用父类的construtor(x,y),相当于ES5中的call。注意的是,super要放在子类构造函数的第一行
this.color=color;
}
}
letcp=newColorPoint(25,8,'green');
module模块
在ES6之前,社区制定了一些模块的加载的方案,最主要的有CommonJS和AMD两种。前者用于服务器,后者用于浏览器。
//CommonJS
let{stat,exists,readFile}=require('fs');
ES6在语言标准的层面上,实现了模块功能,而且实现得相当简单,完全可以取代CommonJS和AMD规范,成为浏览器和服务器通用的模块解决方案。
//ES6模块
import{stat,exists,readFile}from'fs';
export命令
export命令用于规定模块的对外接口。
**一个模块就是一个独立的文件。该文件内部的所有变量,外部无法获取。**你可以理解为一个命名空间~
想要获取模块里面的变量,你就需要导出export:
//profile.js
constname='jiaming';
constsayHi=function(){
console.log('Hi!');
}
export{name,sayHi};
还有一个exportdefault命令,方便用户(开发者啦)不用阅读文档就能加载模块(实际上就是输出一个default变量,而这个变量在import的时候是可以更改的):
//export-default.js
exportdefaultfunction(){
console.log('foo');
}
其他模块加载该模块时,import命令可以为该匿名函数指定任意名字。
//import-default.js
importcustomNamefrom'./export-default';
customName();//'foo'
import命令
import命令用于输入其他模块提供的功能。使用export命令定义了模块的对外接口以后,其他JS文件就可以通过import命令加载这个模块。
//main.js
import{name,sayHi}from'./profile.js';
functionprintName(){
console.log('Mynameis'+name);
}
想要了解更多关于HTML5方面内容的小伙伴,请关注扣丁学堂HTML5培训官网、微信等平台,扣丁学堂IT职业在线学习教育平台为您提供权威的HTML5开发视频,HTML5培训后的前景无限,行业薪资和未来的发展会越来越好的,扣丁学堂老师精心推出的HTML5视频教程定能让你快速掌握HTML5从入门到精通开发实战技能。扣丁学堂H5技术交流群:673883249。
有疑问加站长微信联系(非本文作者)