ES6的笔记
## let声明变量
基本用法:类似var ,但是变量只在代码块内有效 var 和 let 比较
{
let x=10;
var y=15
}
console.log(y)//15
console.log(x)//报错
let不存在变量提升
暂时性死区
es6明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了密闭空间。凡是在声明之前就使用这些变量就会报错
简单来说暂时性死区就是在let的本作用域中 在let之前引用了let的变量
let不允许重复声明斜体样式
允许在块级作用域内声明函数
函数声明类似于var ,即会提升到全局作用域或函数作用域的头部,同时函数声明还会提升到所在的块级作用域的头部
避免在块级作用域内声明函数优先使用函数表达式
let fn=function(){}
//块级作用域必须有大括号
const
const声明的变量为常量,只读,不能更改
const声明变量是立即赋值
const作用域玉let相同,只在声明的块级作用域有效
不存在变量提升
不能重复声明
const保证的是值和引用地址不得更改
const FOO=Object.freeze({a:1,b:2})
冻结对象本身不能添加属性,不能修改属性的值类型
冻结数组本身不能添加元素,不能修改元素的值类型
//Object.keys(obj)返回一个数组,由obj的所有属性或者obj的所有索引
//深拷贝:
function freezeAll(obj){
var ora=Array.isArray(obj)?[]:{};
Object.freeze(obj);
//Object.keys(obj)返回一个数组,由obj的所有属性或者obj的所有索引
Object.keys(obj).forEach(function(item){
if(typeof obj[item]=="object"){
ora[item]=freezeAll(obj[item])
}else{
ora[item]=obj[item]
}
});
return ora;
}
var obj=[1,[2,3,[4,5,[6,7]]]]
var res=freezeAll(obj);
//冻结
const AX=freezeAll(obj)
function freezeAll(obj){
Object.freeze(obj);
// Object.keys(obj)返回一个数组,由obj的所有属性或者obj的所有索引
Object.keys(obj).forEach(function(item){
if(typeof obj[item]=="object"){
obj[item]=freezeAll(obj[item])
}
});
return obj;
}
let a=1,b=2,c=3;
不注册变量成window的属性
没有重复定义
数组的解构赋值
按一定模式从数组或对象中提取值为变量赋值叫做解构
模式匹配,等号左右两边模式相同,不能解构赋值undefined
部分匹配,左边变量少于右边数组
右边不是数组
表达式惰性求值,需要赋值的时候执行表达式
对象的解构赋值
let{a:a,b:b,c:c}={a:1,b:2,c:3}--模式和变量
对象的解构赋值的内部机制,是先找到同名属性,然后再赋值给对应的变量
等号右边数字和布尔值结构先转为对象
字符串
es6用反引号(ESC下)包围变量用${变量}拼接
字符串的方法:str.includes("s") 有没有 返回true和false
str.startsWith("s")是不是在开头
str.endsWith("s")是不是在结尾
str.includes("s",num)
str.startsWith("s",num)从索引最后前num是否以s开头
str.endsWith("s",num)从索引最后前num是否以s解束
str.repeat(n)重复次数,生成新字符串n不是数字会被转成数字,n<=-1报错;-1<n<0,n=NAN解果都为0
str.padStart(n,"xyz")从前面补全字符串,生成新字符串
str.padEnd(n,"y")从后面补全字符串
n:补全之后的长度,y要补充的字符串,重复出现
n=str长度:返回str
重复次数过多超过n,截取后面的多余字符
str.trim()//去除空白返回新字符串
str.trimStart()去除前面空白和str.trimLeft()一样
str.trimEnd()去除后面空格和str.trimRight()一样
空白含:空格 tab键空格 全角空格 半角空格
str.replaceAll("a","m")替换全部
Number.isFinite()只对数值有效,其他类型一律false isFinite()
Number.isNAN()只对数值有效,其他类型一律false isNAN();
Number.parseInt()==parseInt();
Number.parseFloat()==parseFloat();
Number.isInteger();判断是否为整数,非数值返回false
Number.isSafeInteger()判断是否是安全整数(-2的53次方)~(2的53次方)
Number.MAX_SELF_INTEGER
BigInt-大整数
在数字后面加n(标志)
typeof为BigInt()
BigInt(x)x为小数报错,x为NAN报错
Boolean String Number可以将大整数转换
运算与Number一致,除以运算舍弃小数10n/3n=3n;
可用于比较1n<2 true
""+35n="35"
运算(1n*10n)
指数
a**b=Math.pow()
a的b次方
a**b**c===a**(b**c)
Math
Math.trunc()去除小数点,保留整数
非数值转化成数值,转化不了NAN
Math.sign() 正1 负-1 0-0 -0--0 NAN
Math.imul(a,b);a*b
数组Array 扩展运算符…
Math.max(...[123])
let arr=[1,2];var copy=[...arr];
let arr1=[1,2],arr2=[3,4,5]
let arr=[...arr1,...arr2]
const[first,...rest]=[1,2,3,4,5];
let BtnArr=[...document.querySelectorAll(".btn")]
Array.from(),将类数组转化成真正的数组
只要是部署了Iterator接口的数据结构,Array.from都能将其转为数组;
第二个参数回调函数,对数组元素进行处理,将处理之后的值放入返回数组
Array.from(arguments,function(arg){
teturn arg*arg
})
与 ...(扩展运算符)的区别:都是能转化具有Iterator接口的数据为数组
{length:2},...不能转化
Array.from转换对象为[undefined,undefined],...转换对象报错
Map
arr.map(function(value,index,arr){
})
返回新数组,可以对每一项进行修改可以直接通过value改值,forEach不行,只读不写 想要更改要用第三个参数arr[index]进行改值(value = arr【index】*1)
生成1-100
var res=Array.from({length:100}).map(function(v,i){
return v=i+1;
});
或
var res=Array(100).fill(0).map(function(v,i){
return v=i+1;
})
arr.fill(x)填充数组,已有的元素会被覆盖
arr.fill(x,start,end)//起始位置,结束位置(不含)只有开始填充到最后
x是引用类型,填的是指向
Array.of();序列转化成数组
Array.of(1,2,3)==[1,2,3];
[].slice.call(arguments)模拟实现Array.of()
序列变数组Array.of()
类数组变数组Array.from()
数组转序列...(扩展运算符)
Array.copyWithin(目标索引,开始索引,结束索引)
从开始索引到结束索引,复制数组元素,从目标索引开始放在目标索引 负数为倒数
[1,2,3,4,5].copyWithin(0,3) 4,5,3,4,5
arr.find(function(){})返回第一个符合条件的结果,没有则返回undefined
arr.findIndex(function(){})返回第一个符合条件的索引,没有则返回-1
indexOf()不能查找NAN (arr.includes)能查找NAN
arr.keys();获取键
arr.values()获取值
arr.entries()获取键值对
返回数组,遍历器对象,可通过for..of遍历
for(let [k,v] of arr.keys()){ //keys() 数组中的每一项
console.log(k,v)//索引和内容
}
let arr=[1,2,3,4,5];
for(let i of arr){
console.log(i) 直接取值
}
for(let i of arr.keys()){
console.log(i)取索引
}
arr.includes(tag,index) arr中是否包含tag
index,开始索引,默认0,负数从后往前数 负大于长度0
arr.flat(n);拉平数组
用infinity做参数,无论多少维数组都能拉平为一层
arr.flatMap(function(v,i){
对每个元素进行处理(map),在拉平,最后返回一个新数组
})
flatMap只能拉平一层
empty,[,,,]
empty:什么都没有,不是undefined,不是null
forEach,some,every,reduce,filter跳过空元素
map跳过但保留元素显示为(empty)
join,toString将空元素视为undefined,undefined和null视为空
Array.from(),...将空视为undefined 将类似数组的对象转化为真的数组
copyWith拷贝空元素
fill将空视为正常
for...of将空视为undefined
keys,values,entries,find,findIndex将空视为undefined
object
属性简洁表示法
{a:a,b:b}=={a,b},
方法简洁表示法
{a:a,b:b,say:function(){}}==={a,b,say(){}}
对象方法做构造函数方法不能简写
let obj={
fn(){
this.x=100
}
}
属性名表达式
obj.a=10 标志符
obj["b"]=20方括号
let obj={
a:1,
b:2
}
不要用对象做表达式
可枚举,enumerable
对象的每个属性都有个可描述对象,Object.getOwnPropertyDescriptor(obj,xy)
Object.getOwnPropertyDescriptors(obj)方法,返回指定对象的所有自身属性(非继承的属性)的描述对象
enumerable为false,则不可被for in遍历 自身的和继承的
for..in循环:只遍历对象自身的和继承的可枚举属性
Object.keys():返回数组,包含对象自身所有可枚举属性的键名
JSON.stringify():只串行化对象自身的可枚举属性
Object.assign():忽略enumerable为false的属性,只拷贝对象自身的可枚举属性
Object.assign({},obj,变量1,变量2)合并对象,浅拷贝,返回新数组
Object.assign(obj,变量1,变量2)合并对象,浅拷贝
arr.concat()浅拷贝
Object.defineProperty 扩展属性
for..in循环:只遍历对象自身的和继承的可枚举属性
Object.keys(obj):返回数组,包含对象自身所有可枚举属性;
Object.getOwnPropertyNames(objs)数组,包含自身所有属性和自身不可枚举属性的键名(非继承属性)
Object.getOwnPropertySymbols(obj)数组,包含对象自身所有的Symbol属性的键名
Reflect.ownKeys(obj);返回一个数组,包含对象自身的(不含继承的)所有键名,不管键名是Symbol或字符串,也不管是否可枚举
首先遍历所有数值键,按照数值升序排列
其次遍历所有字符串键,按照加入时间升序排列
最后遍历所有的symbol键,按照加入时间升序排列
数据劫持
let obj={}
Object.defineProperty(obj,"a",{
value:200,默认为undefined
enumerable:true,默认为true
writable:true,默认为false
configurable:true;默认为false
})
let obj={}
Object.defineProperty(obj,"a",{
get:function(){
return this.value;
},
set:function(v){
this.value=v;
},
value:200,默认为undefined
enumerable:true,默认为
configurable:true;默认为
})
Object.defineProperty(Array,"shuffle",{
value(arr){
return arr.sort(function(){
return 0.5-Math.random()
})
}
})
Object.defineProperty(Array,"shuffle",{
value:function(arr){
return arr.sort(function(){
return 0.5-Math.random()
})
}
})
console.log(Array.shuffle(arr))
super:指向当前对象的原型对象,只能在对象方法里使用
obj.__proto__读取或设置obj的原型方法 Object.prototype
let obj=Object.create(xy)生成obj的原型对象为xy
Object.setPrototypeOf(obj,mn)设置对象的原型对象
Object.getPrototypeOf(obj)获取对象的原型对象
扩展运算符...的解构赋值
将对象可遍历但没分配的属性拷贝过来
let{a,b...c}={a:1,b:2,m:3,n:4};
a=1,b=2,c={m:3,n:4}
...只能用在最后一个参数
...后面不是对象强制转换成对象
...后面是字符串时,转成类数组
扩展运算符的拷贝
let x={a:1,b:2}
let obj={...x}等价于let obj=Object.assign({},x)//合并对象
只拿到了自身属性,获取自身和原型属性可用:
let obj={
__proto__:Object.getPropertyOf(x),
...x
}
let obj=Object.assign(Object.create(Object.getPrototypeOf(x)),x)
扩展运算符...合并
let x={a:1,b:2};
let y={a:3,d:4};
let obj={...x,...y}等价于let obj=Object.assign({},x,y);
链判断运算符?.
链式调用时判断,如果是null和undefined直接返回undefined
a?.b 属性调用
m?.[1] 索引调用
xiaoming.say?.() 方法调用
短路
delete
报错
括号
null判断??
类似||,设定默认值
如果是null或undefined才生效
let title=a?.b?.title??"Null判断"
与&&或||一起用,必须括号
??和| |效果类似,但是 区别在于??仅代表前面的表达式是null 或者undefined才会执行后面的表达式 。而| |则代表前面的表达式是null或者undefined或者false 或者0才会执行后面的。
Object.keys 返回键
Object.values 返回值
Object.entriess 返回键值对
参数默认值
es6之前设置参数默认值 a=a||100
es6的null判断运算符 a=a??100
es6函数参数默认值 function say(a=100){}默认值严格等于(===)undefined
函数里不能再次用let或const声明参数的同名变量
参数名不能重复
默认值不影响arguments
解构赋值做默认值
function abc({a,b=10}){
console.log(a,b)
}
abc()报错不能解构
abc({}undefined,10)
function abc({a,b=10}={}){
console.log(a,b)
}
abc()undefined,10
abc({}undefined,10)
有默认值的参数不是最后一个参数,调用时不可省略
省略中间参数(5,null,10)
function abc(a,b=5,c){
console.log(a,b,c)5 5 10
}
abc(5,undefined,10)
**长度**
length计算方式:第一个默认值参数(不含)之前的参数个数
var a=100;
function abc(a,b=function(){console.log(a=10)}){
a=25;
b();
console.log(a)10 10
}
abc(50)
rest
参数用...abc形式表示剩余参数,abc为数组
代替了arguments
rest不算入长度
rest必须放最后
严格模式
函数体内不能设置严格模式"use strict"
解决方案:全局设置,立即执行函数设置
箭头函数
let fn=x=>x 相当于:let fn=function(x){
return x;
}
参数说明:1个参数可不加括号,无参数或多个函数要加括号
函数体说明:如果要return,无大括号可不写return
单行执行代码可省略{}
返回对象形式,必须放()里
特点:无arguments对象,用rest代替
this是创建时,不是调用时,箭头函数里没有this,this指向外层代码块不能做构造函数
箭头函数使用要注意什么
(1)函数体内的this指向不固定window,和父级作用域一致
(2)不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
(3)不存在arguments对象,用rest代替该对象在函数体内不存在。如果要用,可以用 rest 参数代替。
(4)不可以使用yield命令,因此箭头函数不能用作 Generator 函数。
(5) 没有prototype(原型)
(6) this指向不能被改变
set
支持forEach遍历
类似数组,每个值都是唯一的{1,2,3,5}
let s=new Set(数组、字符串、NodeList、HTMLCollection、argument等)
s.size 成员数
s.add(x)添加成员,存在则不添加,返回实例本身
s.delete(x)删除成员,返回true或false
s.clear()清楚所有成员
s.has(n);是否有n
set 用for of遍历
let s =new Set([1,2,3,4,5,6]);
for(k of s.leys()){
console.log(k)
}
数组去重
let s=new Set(1,2,2,3,4,3,4,5,2,1)
console.log([...new Set(s)])
let x=new Set(1,3,2,4,5]),y=new Set([2,4,3,6,7]);
交集(公共部分)a,并集(合并,不重复)b,差集(没有对方的)c;
let a=[...x].filter(v=>[...y].includes(v));
let b=new Set([...x,...y]);
let c=[...x].filter(v=>![...y].includes(v));
weakSet
成员是对象或数组
没有size
不可遍历
add,has,delete
弱引用
let ws=new WeakSet([[1,2],[3,4]])
WeakSet和Set区别:
1、WeakSet解构和Set类似,都是不重复值的集合。
2、WeakSet的成员只能是对象,而不能是其他类型的值
3、WeakSet中的对象都是弱引用,即垃圾回收机制不考虑WeakSet对该对象的引用。也就是说,如果其他对象都不再引用该对象,那么垃圾垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象是否还存在于WeakSet之中。(WeakSet里面的引用都不计入垃圾回收机制,适合临时存放一组对象,以及存放跟对象绑定的信息。只要这些对象在外部消失,它在WeakSet里面引用的就会自动消失。)
WeakSet不能遍历,因为成员都是弱引用,随时可以能消失,遍历机制无法保证成员存在。
WeakSet的一个用处是储存DOM节点,而不担心这些节点从文档移除时会引发内存泄露。
Map
存键值对的对象或数组{"yes"=>true,"no"=>false}
size,
.set(key,value);key是任意值返回实例
.get(key)
has(键)
delete、clear
map对象本身就是map.entries()
weakMap 类似Map属性必须是对象(引用类型)
let wm=new weakMap([[{a:1},100,{b:2},200]])
Map
Map转json
属性都是字符串
转成对象,JSON.stringify(obj),JSON.parse(str)
属性不全是字符串
转成数组,JSON.stringify([...map]),JSON.parse(str)
JSON转Map
键名都是字符串
对象转Map
整个JSON是数组,且每个元素又是数组
new Map(JSON)
Proxy Reflect
Proxy是在访问之前做一层拦截,对访问进行处理
let proxy=new Proxy("拦截目标",{拦截行为})
拦截目标:函数,数组,对象
拦截行为-get
get(target,prop,proxy){
return 处理值
}
拦截属性读取
target:拦截目标
prop:属性
proxy:代理器对象 获取:proxy.getReceiver
configurable:false并且writable:false,报错
let obj={a:1,b:2}
let proxy=new Proxy(obj,{
get(t,p){
if(p in t){ 检测t里有没有p属性
return t[p]
}else{
return `没有${p}属性`
}
}
})
获取对象属性,如果属性不存在,则打印 属性xx不存在
检测属性是否存在:if(prop in targer)
if(Reflect.has(targer,prop))
拦截行为set{
set(arguments,value,proxy){
target[prop]=value;
}
拦截赋值操作
value:要修改的值
configurable:false(无法删除)并且writable:false (无法修改)
拦截行为apply
apply(目标函数,this,目标参数实参列表){
return Reflect.apply(...arguments)
}
拦截函数时调用,apply,call,bind()
this:目标函数中的this
Reflect.apply(...arguments)===Reflect.apply(目标函数,this,目标函数的实参列表)
拦截行为 has
has(target,prop){
teturn prop in target;
}
拦截in
Reflect.has(target,prop)
拦截行为defineProperty
defineProperty(target,prop,descriptor){
return
}
拦截Object.defineProperty,让属性不可写,不能添加新属性
deleteProperty
deletePrototypy(t,p){
return t[p];
}
拦截delete,返回false为属性不可删除
拦截行为getOwnPropertyDescriptor
getOwnPropertyDescriptor(t,p){
return;
}
拦截Object.getOwnPrototypeDescriptor,返回不能获取属性描述对象
拦截行为setPrototypeOf
setPrototypeOf(target,proto){
return false;
}
拦截Object(或Reflect).setPrototypeOf()设置原型效果(__proto__),return false为不可设置
取消代理
Proxy.revocable(obj,handler)
返回一个可取消的proxy实例,{proxy,revoke(){}};
Symbol
原始数据类型,表示独一无二的值
let s=Symbol()没有new ,不是对象,类似字符串
let s=Symbol("js")参数只是个描述,用于不同Symbol之间的区分,获取这个参数的描述:s.description
Symbol可以转换字符串和布尔值
Symbol做对象属性
Symbol做对象属性不能用.访问
Symbol设置属性时要用[]
遍历对象Symbol属性
Object.getOwnPropertySymbols()获取所有Symbol的属性
Reflect.ownKeys()获取自身的属性(包含不可枚举的属性,包含Symbol)
Symbol.for(),Symbol.keyFor()
Symbol()!==Symbol()
Symbol.for()生成新的Symbol,可搜索,for登记
使用Symbol.for(参数)先检查有没有相同参数的Symbol,有则返回没有则创建新的Symbol
Symbol.for()===Symbol.for()
Symbol.keyFor(s)返回登记的Symbol的key(参数)只返回Symbol.for()创建的
Iterator
遍历器是一种接口,为不同数据提供一种统一的访问机制,任何部署了iterator接口的数据都可以用for..of遍历
执行过程
创建指针对象,指向数据的起始位置
第一次调用next时,指向第一个成员
第二次调用next时指向第二个成员
一直到数据结束位置
function abc(arr){
var n=0;
return {
next(){
return n<arr.length?{value:arr[n++],done:false}:{value:undefined,done:true};
}
}
}
let x=abc([2,4,5,8])
next返回成员信息
value 返回成员的值
done遍历是否结束
```javascript
Symbol.iterator属性
默认的interator接口部署在Symbol的iterator属性上,Symbol.iterator是遍历器的生成函数,执行这个函数就会返回一个遍历器
Symbol.iterator是表达式,返回Symbol对象的iterator属性(类型Symbol),所以要用[]设置或访问
原生数据具有iterator接口
数组,字符串,map,set,HTMLCollection,NodeList。类数组等
let str="javascript";
let iterator=str[Symbol.iterator]();
iterator.next()
普通对象设置iterator接口
obj[Symbol.iterator]=function(){}
[...obj]
let obj={a:1,b:2};
obj[Symbol.iterator]=function(){
obj没有length,取obj的key
let keys=Object.keys(obj);
keys["a","b"]
let index=0;
return {
next(){
return index<keys.length?{value:[keys[index],obj[keys[index++]]],done:false}:{done:true}
}
}
}
for(let i of obj){
console.log(i)
}
gennertor 异步同步化
ajax回调,异步用同步表示
回调地狱
$(function(){
$.ajax({url:"1.php",success:(data)=>{
var n=data;
console.log(n)
$.ajax({url:`${n}.php`,success:(data1)=>{
var n1=data1;
console.log(n1)
$.ajax({url:`${n1}.php`,success:(data2)=>{
console.log(data2)
}})
}})
}
})
})
解决回调地狱问题
generator:异步问题同步显示
function abc(){
let a=ajax("1.txt");
let b=ajax(a+".txt");
let c=ajax(b+".txt");
console.log(c)
}
function ajax(url,callback){
let xhr.new XMLHttpRequest("get",url);
xhr.send()
xhr.onreadystatechange=function(){
if(xhr.readyState==4){
if(xhr.status==200){
callback(xhr.responseText);
}
}
}
}
function qs(url){
ajax(url,function(dt){
gt.next(dt)
})
}
function* abc(){
let a=yield qs(1.txt);
document.getElementByClassName("res").innnerHTML+=a;
let b=yield qs(b+".txt")
document.getElementByClassName("res").innnerHTML+=b;
let c=yield qs(c+".txt")
document.getElementByClassName("res").innnerHTML+=c;
console.log(c)
}
let gt=abc()
promise:
ajax("1.txt").then(()=>{return ajax("2.txt")}).then().then()
promise
异步编程解决方案
保存着未来才会结束的事件结果
特点:
1.状态不受外界影响,3个状态,pending进行,fulfilled已成功,rejected已失败,只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态
2.状态改变:pending->fulfilled,pending->rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved
promise基本用法
let promise=new Promise((resolve,reject)=>{
if(异步操作成功){
resolve(value);padding->resolve未完成到成功,异步操作成功调用,将值(value)做参数传递出去
}else{
reject(error);pending->rejected未完成到失败,将异步操作的错误传递出去
}
})
promise的then
promise对象的then方法分别指定resolved和rejected回调函数
promise.then(function(value){
成功的操作
},function(error){
失败的操作
})
promise的简单例子
setTimeout第三个参数:给第一个参数传参
function abc(ms){
return new Promise((resolve,reject)=>{
setTimeout(resolve,ms,"aaaa");
setTimeout(reject,5000,"错误")
throw new Error("错误")
})
}
abc(1000).then((value)=>console.log(value),(txt)=>console.log(txt))
throw 抛出错误
throw new Error("错误")
try{尝试
console.log(a)
}catch(err){捕捉
console.log(err)
}
finally{最终
console.log(end)
}
promise立即执行
实例中直接调用resolve或rejected方法
function abc(){
return new Promise((resolve,reject)=>{
console.log(3);
resolve()
})
}
abc.then(function(){
console.log(1)
})
console.log(2)
promise封装图片加载
function loadImage(url){
return new Promise((resolve,reject)=>{
var img=new Image();
img.src=url;
img.onload=function(){
resolve(this);
}
img.onerror=function(){
reject()
}
})
}
loadImage(url).then((img)=>{
document.body.insertBefore(img,document.body.firstChild),
()=>{
console.log("加载失败")
}
})
promise封装getJson方法
function getJson(url){
return new Promise((resolve,reject)=>{
let xhr=new XMLHttpRequest();
xhr.open("get",url);
xhr.responseType="json";
xhr.setRequestHeader("Accept","application/json");
xhr.send();
xhr.onreadystatechange=function(){
if(xhr.readyState!=4){
return;
}else{
if(xhr.status==200){
resolve(xhr.reponse)
}else{
reject(xhr.statusText)
}
}
}
})
}
getJson(文件名.json).then((data)=>{console.log(data)},(txt)=>{console.log(txt)})
promise嵌套
一个resolve用另一个promise做参数
let a=new Promise((rv,rj)=>{
setTimeout(()=>{rv()},5000)
}).then(()=>console.log(5000))
let b=new Promise((rv,rj)=>{
setTimeout(()=>{rv(a)},1000)
}).then(()=>console.log(1000))
return
resolve,reject不中断后面语句执行,想要阻止用return resolve()
then
then有两个参数,接收promise的resolve和reject
then里的resolve返回结果,作为下一个then的resolve参数(链式调用)
Promise.prototype.catch
catch接收错误(promise错误,throwError,then错误)
catch接收前面所有的错误,不接收后面错误,无错误则跳过
不推荐reject,推荐catch
.then().catch(()=>{})
finally(()=>{})
通常放在最后面,finally()方法用于指定不管 Promise 对象最后状态如何,都会执行的操作