版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
ES6语法详解(二)
一、Promise
Promise是一个对象,代表了未来某个将要发生的事件(,这个事件诵常是一个异步操
作)
有了Promise对象,可以将异步操作以同步的流程表达出来,避免了层层嵌套的回调
函数(俗称'回调地狱’)。
ES6的Promise是一个构造函数用来生成promise实例。
1、promise对象3个状态
•pending:初始化状态
•fullfilled:成功状态
•rejected:失败状态
只有异步操作的结果,可以决定当前是哪一种状态,任何其也操作都无法改变这个状态。
这也是Promise这个名字的由来,它的英语意思就是"承诺",表示其他手段无法改变。
一旦状态改变,就不会再变,任]可时候都可以得到这个结果。
Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending
变为只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,
rejectedo
这时就称为resolved(已定型).
2、使用方法
1、创建一个promise实例对象,参数是一个匿名函数,这个匿名函数有两个参数,
resolve和reject,
2、每一个参数都是一个回调函数。然后,函数体中T殳执行的是异步操作,比如发起
Ajax请求,或者开启定时器等。
3、异步操作成功时,调用resolve回调函数,异步操作失败时,调用reject回调函数。
4、在初始化Promise实例对象的时候,Promise的状态为pending;在调用resolve
回调函数的时候,Promise的状态为fullfilled,表示成功状态;在调用reject回调函数的
时候,Promise的状态为rejected,表示失败状态;
5、Promise的实例对象有一个方法then,参数为两个匿名函数,第一个匿名函数处
理Promise的状态为fullfilled的情况;第二个匿名函数处理Promise的状态为rejected
的情况;
6、上面说到,在异步操作成功或者失败的时候,会调用resolve和reject函数,在这
两个回调函数中可以传入参数,这个参数可以直接带入到then中两个匿名函数的参数中使
用。比如获取到ajax的数据,可以将获取的数作为参数传入resolve的参数中,然后会自
动将这个参数传入then的第一个匿名函数中,reject也一样。
用代码表示:
functiontimeout(ms){
returnnewPromise((resolve,reject)=>{
setTimeout(resolve,ms,'done');
});)
timeout(100).then((value)=>{
console.log(value);});
用图示的方法表示:
示例:
letpromise=newPromiseffresolve,reject)=>{
console.log(lll);
//执行异步操作
setTimeout(()=>{
console.log(222);
//执行异步操作成功,此时修改promise的状态fullfilled
resolve("success!");
//执行异步操作成功,此时修改promise的状态rejected
reject("failed!");
},2000);
});
promise.then((data)=>{//promise的状态fullfilled的操作
console.log("成功",data);
},()=>{//promise的状态rejected的操作
console.log("失败",data);
});
注意:当执行到resoke("success!");修改promise的状态fullfilled的时候,后面
的reject("failed!)不会执行,也就不会打印8、。拈」。9("失败");的语句。
3、promise执行顺序
Promise新建后就会立即执行。
letpromise=newPromise(function(resolve,reject){
console.log('Promise');
resolve();
});
promise.then(function(){
console.logCresolved.');
));
console.log('Hi!");
〃Promise
//Hi!
//resolved
上面代码中,Promise新建后立即执行,所以首先输出的是Promise.然后,then方法指
定的回调函数,将在当前脚本所有同步任务执行完才会执行,所以resolved最后输出。
newPromise((resolve,reject)=>{
resolve(l);
console」og(2);
}).then(r=>{
console.log(r);
});
//2
//I
上面代码中,调用resolveQ)以后,后面的8、。后1。9出还是会执行,并且会首先打
印出来。这是因为立即resolved的Promise是在本轮事件循环的末尾执行,总是晚于本
轮循环的同步任务。
然而一
一般来说,调用reserve或reject以后,Promise的使命就完成了,后继操作应该放
到then方法里面,而不应该直接写在resolve或reject的后面。所以,最好在它们前面加
上return语句,这样就不会有意外。
newPromise((resolve,reject)=>{
returnresolve(l);
//后面的语句不会执行
console.log(2);
})
4、小例子
使用promise获取新闻内行口评论内容:
//定义一个请求news的方法
functiongetNews(url){
〃创建一个promise对象
letpromise=newPromise((resolve,reject)=>{
〃初始化promise状态为pending
〃启动异步任务,发起Ajax请求
〃:L.创建一个XMLHttpRequest类型的对象
letrequest=newXMLHttpRequest();
//4,指定xhr状态变化事件处理函数
request.onreadystatechange=function(){
if(request.readyState===4){
if(request.status===200){
letnews=request.response;
resolve(news);
}else{
rejec"请求失败了.」);
)
)
);
request.responseType:'json';〃设置返回的数据类型
//2.打开与一个网址之间的连接
request.openCGET",url);〃规定请求的方法,创建链接
//3.通过链接发送一次请求
request.send。;〃发送
))
//只有将promise返回,才可以调用then方法
returnpromise;
};
//调用getNews,获取新闻内容,其中一个字节为评论内容的地址
getNews('http://localhost:3000/news?id=2')
.then((news)=>{
//获取到新闻内容
console.log(news);
//document.write(JSON.stringify(news));
//获取新闻内容中的评论地址
console.log('http://localhost:3000'+mentsUrl);
//递归获取新闻评论内容,并且返回promise对象,以便链式then方法。
returngetNews('http://localhost:3000,+mentsUrl);
L(error)=>{
alert(error);
))
.then((comments)=>{//then方法可以链式编程
console.log(comments);
//把新闻的评论部分已json的格式打印出来显示
document.write('<br><br><brxbrxbr>'+JSON.stringify(comments));
},(error)=>{
alert(error);
});
5、catch
Ptotype.catch方:去是.then(null,rejection)或.then(undefined,
rejection)的别名,用于指定发生错误时的回调函数。
当状态就会变为rejected,就会调用catch方法指定的回调函数,处理这个错误。另
外,then方法指定的回调函数,如果运行中抛出错误,也会被catch方法捕获。
newPromise((resolve,reject)=>{
reject(l);
console.log(2);
}).catch(r=>{
console.log(r);
});
//2
//I
一般来说,不要在then方法里面定义Reject状念的回调因数(即then的第二个
参数),总是使用catch方法。
//不好的写法
promise
.llien(funcliuri(ddld){
//success
},function(err){
//error
});
//好的写法
promise
.then(function(data){//co
//success
})
.catch(function(err){
//error
});
上面代码中,第二种写法要好于第一种写法,理由是第二种写法可以捕获前面then方
法执行中的错误,也更接近同步的写法(try/catch)。因此,建议总是使用catch方法,
而不使用then方法的第二个参数。
6、finally
finally方法用于指定不管Promise对象最后状态如何,都会执行的操作。该方法是
ES2018引入标准的。
promise.then(result=>{-}).catch(error=>{…}).finally(()=>{•});
上面代码中,不管promise最后的状态,在执行完then或catch指定的回调函数以
后,都会执行finally方法指定的回调函数。
7、Promise静态方法
7.1、all和race
有时候需要同时处理多个ajax请求,如何在都获取到数据的时候才进行下一步
操作呢?
Promise.all就派上用场了。
Promise.all([ajaxl(),ajax2(),ajax3()])
.then(function(res){
//res处理
})
.catch(function(err){
//err曾吴姐里
})
其中ajaxl,ajax2,ajax3返回值都是Promise实例。
当ajaxl(),ajax2(),ajax3()状态全为fulfilled的时候,才会调用then方法。
当ajaxl(),ajax2(),ajax3()状态有一个为rejected的时候,就会调用catch方法。
而rece与all用法相同,但是结果相反:
Promise.rece([ajaxlO,ajax2(),ajax3()])
.then(function(res){
//res处理
})
.catch(function(err){
//err错误处理
})
当ajaxlO,ajax2(),ajax3()状态有一个为fulfilled的时候,就会调用then方法。
当ajaxl(),ajax2(),ajax3()状态全为rejected的时候,才会调用catch方法。
7.2、resolve和reject
Promise.resolve(value)方法返回一个已给定值解析后的新的Promise对象,从而能
继续使用then的链式方法调用。
varpromisel=Promise.resolve(123);
promise.then(function(value){
console.log(value);
〃expectedoutput:123
));
而Promise.rejectO和resolve一样。
二.Symbol
ES5的对象属性名都是字符串,这容易造成属性名的冲突。比如,你使用了一个他人
提供的对象,但又想为这个对象添加新的方法(mixin模式),新方法的名字就有可能与
现有方法产生)中突。如果有一种机制,保证每个属性的名字都是独一无二的就好了,这样就
从根本上防止属性名的冲突。这就是ES6引入Symbol的原因。
1、Symbol属性对应的值是唯一的,解决命名冲突问题
Symbol是一种新的数据类型,跟String,Number,Object,Boolean,null,
undefined并列。
Symbol值通过Symbol函数生成。这就是说,对象的属性名现在可以有两种类型,
一种是原来就有的字符串,另一种就是新增的Symbol类型。凡是属性名属于Symbol类
型,就都是独一无二的,可以保证不会与其他属性名产生冲突。
lets=SymbolQ;
typeofs;//symbol
上面代码中,变量s就是一个独一无二的值。typeof运算符的结果,表明变量s是
Symbol数据类型,而不是字符串之类的其他类型。
注意,Symbol函数前不能使用new命令,否则会报错。这是因为生成的
Symbol是一个原始类型的值,不是对象。也就是说,由于Symbol值不是对象,
所以不能添加属性。基本上,它是一种类似于字符串的数据类型。
Symbol函数可以接受一个字符串作为参数,表示对Syrrbol实例的描述,主要是为
了在控制台显示,或者转为字符串时,比较容易区分。
letsi=Symbol('foo');
lets2=Symbol('bar');
si//Symbol(foo)
s2//Symbol(bar)
sl.toStringQ//"Symbcl(foo)"
s2.toString()//"Symbcl(bar)"
上面代码中,S1和s2是两个Symbol值。如果不加参数,它们在控制台的输出都是
SymbolO,不利于区分。有了参数以后,就等于为它们加上了描述,输出的时候就能够分
清,到底是哪一个值。
2、Symbol值不能与其他数据进行计算,包括同字符串拼串
letsym=Symbol('Mysymbol');
"yoursymbolis"+sym
//TypeError:can'tconvertsymboltostring
yoursymbolis${sym}'
//TypeError:can'tconvertsymboltostring
3、作为属性名的Symbol
由于每一个Symbol值都是不相等的,这意味着Symbol值可以作为标识符,用于对象
的属性名就能保证不会出现同名的属性。这对于一个对象由多个模块构成的情况常有用,
能防止某一个键被不小心改写或覆盖。
letmySymbol=SymbolO;
//第一种写法
leta={};
a[mySymbol]="Hello!';
//第二种写法
leta={
[mySymbol]:'Hello!'
);
//第三种写法
leta={};
Object.defineProperty(a,mySymbol,{value:'Hello!"');
//以上写法都得到同样结果
a[mySymbol]//"Hello!"
注意,Symbol值作为对象属性名时,不能用点运算符。
a.mySymbol='Hello!';
4、forin,forof遍历时不会遍历symbol属性
letobj={
username:'Daotin,,
age:18
};
obj[symbol]='hello';
obj[symbol]='symbol,;
console.log(obj);
for(letiinobj){
console.log(i);
)
5、内置的Symbolfi
除了定义自己使用的Symbol值以外,ES6还提供了11个内置的Symbol值,指
向语言内部使用的方法。
6、Symbol.haslnstance
对象的Symbol.haslnstance属性,指向一个内部方法。当其他对象使用instanceof
运算符,判断是否为该对象的实例时,会调用这个方法。比如,fooinstanceofFoo在语
吉内部,实际调用的是FoofSymbol.hasInstanceKfoo),
7、Symbol.iterator
对象的Symbol.iterator属性,指向该对象的默认遍历器方法。
三、Iterator
Iterator是迭代器(遍历器)的意思。
JavaScript原有的表示"集合"的数据结构,主要是数组(Array)和对象(Object),ES6
又添加了M叩和Set。这样就有了四种数据集合,用户还可以组合使用它们,定义自己的
数据结构,比如数组的成员是Map,Map的成员是对象。这样就需要一种统一的接口机制,
来处理所有不同的数据结构。
遍历器(Iterator)就是这样一种机制。它是一种接口,为各种不同的数据结构提供统一的
访问机制。任何数据结构只舞E署Iterator接口,就可以完成遍历操作(即依次处理该数
据结构的所有成员)。
Iterator的作用:
•为各种数据结构,提供一个统一的、简便的访问接口
•使得数据结构的成员能够按某种次序排列
•ES6创造了一种新的遍历命令for...of循环,Iterator接口主要供for...of消费。
Iterator的遍历过程:
(1)创建一个指针对象,指向当前数据结构的起始位置。也就是说,遍历器对象本质上,
就是一个指针对象。
(2)第一次调用指针对象的next方法,可以将指针指向数据结构的第一个成员。
(3)第二次调用指针对象的next方法,指针就指向数据结构的第二个成员。
(4)不断调用指针对象的next方法,直到它指向数据结构的结束位置。
每一次调用next方法,都会返回数据结构的当前成员的信息。具体来说,就是返回一个包
含value和done两个属性的对象。其中,value属性是当前成员的值,done属性是一个
布尔值,表示遍历是否结束。
下面是一个模拟next方法返回值的例子。
varit=makelterator(['a\"b']);
it.nextO//{value:"a",done:false}
it.next()//{value:"b",done:false}
it.nextO//{value:undefined,done:true}
functionmakelterator(array){
varnextindex=0;
return{
next:function(){
returnnextindex<array.length?
{value:array[nextlndex++],done:false}:
{value:undefined,done:true};
)
);
)
对于遍历器对象来说,done:false和value:undefined属性都是可以省略的,因此上面的
makeiterator函数可以简写成下面的形式。
functionmakelterator(array){
varnextindex=0;
return{
next:function(){
returnnextindex<a-ray.length?
{value:array[nextlndex++]}:
{done:true};
)
);
)
1、默认Iterator接口
ES6规定,默认的Iterator接口部署在数据结构的Symbol.iterator属性,或者说,
一个数据结构只要具有Symboliterator属性,就可以认为是"可遍历的"(iterable)°
Symbol.iterator属性本身是一个函数,就是当前数据结构默认的遍历器生成函数。执
行这个函数,就会返回一个遍历器。至于属性名Symbol.iterator,它是一个表达式,返回
Symbol对象的iterator属性,这是一个预定义好的、类型为Symbol的特殊值,所以要
放在方括号内.
constobj={
[Symbol.iterator]:function(){
return{
next:function(){
return{
value:1,
done:true
});
上面代码中,对象。切是可遍历的(iterable),因为具有SymboLiterator属性。执
行这个属性,会返回一个遍历器对象。该对象的根本特征就是具有next方法。每次调用next
方法,都会返回一个代表当前成员的信息对象,具有value和done两个属性。
ES6的有些数据结构原生具备Iterator接口(比如数组),即不用任1可处理,就可以
被for...of循环遍历。原因在于,这些数据结构原生部署了SymboLiterator属性(详见下
文),另外一些数据结构没有(比如对象)o凡是部署了SymboLiterator属性的数据结构,
就称为部署了遍历器接口。调用这个接口,就会返回一个遍历器对象。
原生具备Iterator接口的数据结构如下。
♦Array
•Map
•Set
•String
•TypedArray
•函数的arguments对象
•NodeList对象
下面的例子是数组的SymboLiterator属性。
letarr=「a'Jb'Jc'];
letiter=arr[Symbol.iteratcr]();
iter.nextQ//{value:'a',done:false}
iter.nextO〃{value:'b',done:false}
iter.nextQ//{value:'c\done:false}
iter.nextO//{value:undefined,done:true}
上面代码中,变量arr是一个数组,原生就具有遍历器接口,部署在arr的
SymboLiterator属性上面。所以,调用这个属性,就得到遍历器对象。
对于原生部署Iterator接口的数据结构,不用自己写遍历器生成函数,for...of循环会
自动遍历它们。除此之外,其他数据结构(主要是对象)的Iterator接口,都需要自己在
Symbol.iterator属性上面部署,这样才会被for...of循环遍历。
一个对象如果要具备可被for...of循环调用的Iterator■接口,就必须在
Symbol.iterator的属性上部署遍历器生成方法(原型链上的对象具有该方法也可)。
2、调用Iterator接口的场合
使用解构赋值以及…三点运算符时会调用iterator接口
letarrl=[1.2,3,4,5];
let[valuel,...arr2]=arrl;
for.,of..遍历
〃原生测试数组
letarr3=[1,2,'kobe',true];
for(letiofarr3){
console.log(i);
)
//字符串string
letstr='abcdefg';
for(letitemofstr){
console.log(item);
)
四.Generator
Generator函数是ES6提供的一种异步编程解决方案。
Generator函数有多种理解角度。语法上,首先可以把它理解成,Generator函数是
一个状态机,封装了多个内部状态。
执行Generator函数会返回一个遍历器对象,也就是说,Generator函数除了状态
机,还是一个遍历器对象生成函数。返回的遍历器对象,可以依次遍历Generator函数内
部的每一个状态。
形式上,Generator函数是一个普通函数,但是有两个特征。
-是,function关键字与函数名之间有一个星号;
二是,函数体内部使用yeld表达式,定义不同的内部状态(yield在英语里的意思就
是"产出")0
function*myGeneratorQ{
yield'hello';
yield'world,;
returnending";
)
//返回值是一个遍历器对象
varhw=myGeneratorQ;
上面代码定义了一个Generator函数helloWoridGenerator,它内部有两个yield表
达式(hello和world),即该函数有三个状态:hello,world和return语句(结束执
行)。
然后,Generator函数的调用方法与普通函数一样,也是在函数名后面加上一对圆括
号。不同的是,调用Generator函数后,该函数并不执行,返回的也不是函数运行结果,
而是一个指向内部状态的指针对象,也就是上一章介绍的遍历器对象(IteratorObject).
下一步,必须调用遍历器对象的next方法,使得指针移向下一个状态。也就是说,每
次调用next方法,内部指针就从函数头部或上一次停下来的地方开始执行,直到遇到下一
个yield表达式(或return语句)为止。换言之,Generator函数是分段执行的,yield
表达式是暂停执行的标记,而next方法可以恢复执行。
hw.ncxt()//{value:'hello',done:false}
hw.next()//{value:'world',done:false}
hw.next()//{value:'ending',done:true}
hw.next()//{value:undefined,done:true}
总结一下,调用Generator函数,返回一个遍历器对象,代表Generator函数的内
部指针。以后,每次调用遍历器对象的next方法,就会返回一个有着value和done两个
属性的对象。value属性表示当前的内部状态的值,是yield表达式后面那个表达式的值;
done属性是一个布尔值,表示是否遍历结束。
1、yield表达式
由于Generator函数返回的遍历器对象,只有调用next方法才会遍历下一个内部状
态,所以其实提供了一种可以暂停执行的函数。yield表达式就是暂停标志。
遍历器对象的next方法的运行逻辑如下:
(1)遇到yield表达式,就暂停执行后面的操作,并将紧跟在yield后面的那个表达
式的值,作为返回的对象的value属性值。
(2)下一次调用next方法时,再继续往下执行,直到遇到下一个yield表达式。
(3)如果没有再遇到新的yield表达式,就一直运行到函数结束,直到return语句为
止,并将return语句后面的表达式的值,作为返回的对象的value属性值。
(4)如果该函数没有return语句,则返回的对象的value属性值为undefined.
需要注意的是,yield表达式后面的表达式,只有当调用next方法、内部指针指向该
语句时才会执行,因此等于为JavaScript提供了手动的"惰性求值"(LazyEvaluation)
的语法功能。
yield表达式与return语句区别:
相似之处在于都能返回紧跟在语句后面的那个表达式的值。区别在于每次遇到yield,
函数暂停执行,下一次再从该位置继续向后执行,而return语句不具备位置记忆的功能。
一个函数里面,只能执行一次(或者说一个)return语句,但是可以执行多次(或者
说多个)yield表达式。
正常函数只能返回一个值,因为只能执行一次return;Generator函数可以返回一系
列的值,因为可以有任意多个yield。
2、与Iterator接口的关系
任意一个对象的Symbol.iterator方法,等于该对象的遍历器生成函数,调用该函数会
返回该对象的一个遍历器对象。
由于Generator函数就是遍历器生成函数,因此可以把Generator赋值给对象的
Symbol.iterator属性,从而使得该对象具有Iterator接口。
varmylterable={};
myIterable[Symbol.iterator]=function*(){
yield1;
yield2;
yield3;
);
[...mylterable]//[1,2,3]
上面代码中,Generator函数赋值给Symbol.iterator属性,从而使得mylterable对象具
有了Iterator接口,可以被…运算符遍历了。
3、next方法的参数
表达式本身没有返回值或者说总是返回方法可以带一个参数,
yieldundefinedonext
该参数就会被当作上一个yield表达式的返回值。
function*f(){
for(vari=0;true;i++){
varreset=yieldi;
if(reset){i=-1;}
)
)
varg=f();
g.nextO//{value:0,done:false}
g.next()//{value:1,done:false}
g.next(true)//{value:0,done:false}
上面代码先定义了一个可以无限运行的Generator函数f,如果next方法没有参数,
每次运行到yield表达式,变量reset的值总是undefined,当next方法带一个参数true
时,变量reset就被重置为这个参数(即true),因此i会等于-1,下一轮循环就会从-1
开始递增。
4、for...of循环
for...of循环可以自动遍历Generator函数时生成的Iterator对象,且此时不再需要
调用next方法。
function*foo(){
yield1;
yield2;
yield3;
yield4;
yield5;
return6;
)
for(letvoffoo()){
console.log(v);
)
//12345
上面代码使用for...of循环,依次显示5个yield表达式的值。这里需要注意,一旦
next方法的返回对象的done属性为true,for...of循环就会中止,且不包含该返回对象,
所以上面代码的return语句返回的6,不包括在for...of循环之中。
下面是一个利用Generator函数和foj.of循环,实现斐波那契数列的例子。
function*foo(){
let[prev,current]=[0,1];
for(;;){
yieldcurrent;
[prev,current]=[current,prev+current];
)
)
for(letnoffoo()){
if(n>1000)break;
console.log(n);
)
Generator小案例
需求:
L发送Ajax请求获取新闻内容
2、新闻内容获取成功再次发送请求获取对应的新闻评论内容
3、新闻内容获取失败则不需要再次发送请求。
functiongetNews(url){
$.get(url,function(data){
console.log(data);
leturls="http://localhost:3000"+mentllrl;
//urls可以作为第一个yield的返回值
//执行第二条yeild语句,发送请求新闻评论
//获取的评论地址妇何传入到yieldgetNews(urls);靠的是第二次
//发送next时传入的参数,就是评论地址
sx.next(urls);
function*sendXml(){
//发送请求新闻内容
leturls=yieldgetNews("http://localhost:3000/news?id=2");
〃请求新闻评论内容
yieldgetNews(urls);
letsx=sendXml();
//执行第一条yeild语句,发送请求新闻
sx.next();
五、async
ES2017标准引入了async函数,使得异步操作变得更加方便。
async函数是什么?一句话,它就是Generator函数的语法糖。
语法:
asyncfunctionfoo(){
await异步操作;
await异步操作;
)
特点:
1、不需要像Generator去调用next方法,遇到await等待,当前的异步操作完成就往下
执行
2、返回的总是Promise对象,可以用then方法进行下一步操作
3、async取代Generator函数的星号*,await取代Generator的yield
4、语意上更为明确,使用简单,经临床验证,暂时没有任何副作用
举个栗子:
asyncfunctiontimeout(ms){
returnnewPromise(resolve=>{
setTimeout(resolve,ms);
})
)
asyncfunctionasyncPrint(value,ms){
console.log('函数执彳亍newDate().toTimeString());
awaittimeout(ms);
console.log('延时时间newDate().toTimeStringO);
console.log(value);
console.log(asyncPnnt('helloasync',2000));
asyncPrint执行的时候,先打印的是"函数执行",之后进入到timeout函数,由
于是异步执行,但是timeout未执行完成,所以await在等待,相当于挂起。而这一边
asyncPrint会立即返回一个Promise对象。之后另一边timeout、执行完成,打印出"延
时时间”,之后打印"hell。async"。
async函数内部return语句返回的值会成为then方法回调函数的参数。下面代码中,
函数f内部return命令返回的值,会被then方法回调函数接收到。
asyncfunctionf(){
return'helloworld';
)
f().then(v=>console.log(v))
//'helloworld"
1、await命令
正常情况下,await命令后面是一个Promise对象。如果不是,会被转成一个立即
resolve的Promise对象。
而resolve参数就是await的返回值。
asyncfunctionf(){
returnawait123;
)
f().then(v=>console.log(v))
//123
await命令后面的Promise对象如果变为reject状态,则reject的参数会被
catch方法的回调函数接帼IJ。
asyncfunctionf(){
awaitPromise.reject('出错了');
)
f()
.then(v=>console.log(v))
.catch(e=>console.log(e))
//出错了
2、案例:获取新闻和评论内容
asyncfunctionsendXml(url){
returnnewPromise((resolve,reject)=>{
$.ajax({
url,
type:'GET',
success:data=>resolve(data),
error:error=>reject(error)
})
})
)
asyncfunctiongetNews'url){
letresult=awaitsendXml(url);
letresult2=awaitsendXml(url);
console.log(result,result2);
getNews('http://localhost:3000/news?id=2')
六、Class
JavaScript语言中,生成实例对象的传统方法是通过构造函数。下面是一个例子。
functionPoint(x,y){
this.x=x;
this.y=y;
)
Ptotype.toString=function(){
return'('+this.x+丁+this.y+')';
);
varp=newPoint(l,2);
上面这种写法跟传统的面向对象语言(比如C++和Java)差异很大,ES6提供了更
接近传统语言的写法,引入了Class(类)这个概念,作为对象的模板。通过class关键字,
可以定义类。
〃定义类classPoint{
constructor(x,y){
this.x=x;
this.y=y;
toStringO{
return'('+this.x++this.y+
})
1、constructor方法
constructor方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。
一个类必须有constructor方法,如果没有显式定义,一个空的constructor方法会被默认
添加。
Class的继承
Class可以通过extends关键字实现继承,这比ES5的通过修改原型链实现继承,要
清晰和方便很多。
classPoint{}//ColorPoint继承PointclassColorPointextendsPoint{}
上面代码定义了一个ColorPoint类,该类通过extends关健字,继承了Point类的所
有属性和方法。
classColorPointextendsPoint{
constructor(x,y,color){
super(x,y);//调用父类的constructor(x,y)
this.color=color;
)
toStringO{
returnthis.color+''+super.toStringO;II调用父类的toStringO
})
上面代码中,constructor方法和toString方法之中,都出现了super关键字,它在
这里表示父类的构造函数,用来新建父类的this对象。
子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为
子类自己的this对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性
和方法,然后再对其进行加工,加上子类自己的实例属性和方法。如果不调用super方法,
子类就得不到this对象。
七、字符串的扩展
includes(str):判断是否包含指定的字符串
startsWith(str):判断是否以指定字符串开头
endsWith(str):判断是否以指定字符串结尾
repeat(count):重复指定次数
letstr='abcdefg';
console.Iog(str.includes('a'));//true
console.log(str.includesCh'));//false
//startsWith(str):判断是否以指定字符串开头
console.log(str.startsWith('ab'));//true
console.log(str.startsWith('ac'));//false
//endsWith(str):判断是否以指定字符串结尾
console.log(str.endsWith('fg'));//true
console.log(str.endsWith('d'));//false
//repeat(count):重复指定次数a
console.log(str.repeat(3));//abcdefgabcdefgabcdefg
二.数值的扩展
二进制与八进制数值表示法:二进制用0b开头,八进制用0。开头。
Number.isFinite(i):判断是否是有限大的数
Number.isNaN(i):判断是否是NaN
Number.islnteger(i):判断是否是整数
Number.parselnt(str):将字符串转换为对应的数值
Math.trunc(i):直接去除小数部分
console.log(OblOlO);//10
console.log(0o56);//46
console.logC------------------------');
//Number.isFinite(i):判断是否是有限大的数
console.log(Number.isFinite(NaN));//false
console.log(Number.isFinite(5));//true
console.log(Number.isFinite(Infinity));//false
console.logC------------------------');
//Number.isNaN(i):判断是否是NaN
console.log(Number.isNaN(NaN));//true
console.log(Number.isNaN(5));//false
console.log(Number.isNaN(undefined));//false
console.logC1);
//Number.islnteger(i):判断是否是整数
console.log(Number.isInteger(5.23));//false
console.log(Number.isInteger(5.0));//true
console.log(Number.isInteger(5));//true
console.logC------------------------');
//Number.parselnt(str):将字符串转换为对应的数值
console.log(Number.parseInt('123abc'));//123
console.log(Number.parseInt('al23abc'));//NaN
console.logC------------------------');
//Math.trunc(i):直接去除小数部分
console.log(Math.trunc(13.123));//13
三.数组扩展
Array.from(v):将伪数组对象或可遍历对象转换为真数组
Array.ofCvl,v2,v3):将一系列值转换成数组
find(function(value,index,arr){returntrue}):找出第一个满足条件返回true
的元素
findlndex(function(value,index,arr){returntrue}):找出第一个满足条件返回
true的兀素下标
<body>
(button〉测试l</button>
<br>
〈button〉测试2</button>
<br>
〈button〉测试3〈/button〉
<br>
<!-l.Array.from(v):将为数组对象或可遍历对象转换为真数组2.Array.of(vl,v2,v3):
将一系列值转换成数组3.find(function(value,index,arr){returntrue)):找出第一个满足条
件返回true的元素4.findlndex(function(value,index,arr){returntrue}):找出第一个满足条
件返回true的元素下标
<scripttype="text/javascript">
//Array.from(v):将伪数组对象或可遍历对象转换为真数组,返回值即为真数组
//使用DOM操纵获取的元素集合是伪数组。
letbtns=document.getElementsByTagName('button');
console.log(btns.length);//3
Array.from(btns).forEach(function(item,index){
co
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2027届高三英语一轮复习课件:专题三 动词的时态、语态和主谓一致
- 2026吉林通化辉南县人力资源和社会保障局就业见习人员招聘54人考试参考题库及答案解析
- 2026四川德阳市公安局经济技术开发区分局招聘第二批警务辅助人员30人考试备考试题及答案解析
- 2026四川绵阳数据发展有限公司招聘公司第二批员工18人笔试备考试题及答案解析
- 2026上海复旦大学智慧纳米机器人与纳米系统国际研究院招聘工程实验人员1名笔试备考试题及答案解析
- 危险废物运输预案
- 2026西安建筑科技大学招聘专职辅导员17人笔试模拟试题及答案解析
- 烧碱生产工岗前交接考核试卷含答案
- 石膏装饰板加工工安全知识竞赛考核试卷含答案
- 资产管理师安全生产知识强化考核试卷含答案
- 室内水箱拆除施工方案
- 河南建院考试单招题目及答案
- 盐城广播电视总台招聘3人笔试模拟试题附答案详解
- 钢筋加强施工方案
- 2025年入党积极分子培训考试试题库及答案
- 快速康复在骨科护理中的应用
- 狭窄性腱鞘炎讲解
- 液氧储罐安全培训
- 骨科第一季度院感工作总结
- 2025年宁夏银川市唐徕中学南校区中考模拟(一模)考试数学试题
- 2025-2026学年高一上学期《循梦而行向阳而生》主题班会课件
评论
0/150
提交评论