ES6相關(guān)知識(shí)總結(jié)

強(qiáng)烈推薦阮一峰老師es6

常量

  • ES5 中常量的寫法(借助 Object.defineProperty 實(shí)現(xiàn))
Object.defineProperty(window,'PI2',{
  value : 3.1415926,
  writable : false //通過將其屬性設(shè)置為不可寫,實(shí)現(xiàn)常量
})
  • ES6 中常量的定義(使用 const
const PI=3.1415926

作用域

  • ES5 使用立即執(zhí)行函數(shù)實(shí)現(xiàn)
;(function(){
  var a=1
  console.log(a) // 1
})()
console.log(a) //a is not defined

此時(shí)在該立即執(zhí)行函數(shù)外打印 a 會(huì)報(bào)錯(cuò),未定義

  • ES6 使用 {} 實(shí)現(xiàn)塊級(jí)作用域
{
  let b=2
  console.log(b) //2
  {
    let b=3
    console.log(b) //3
  }
  console.log(b) //2
}
console.log(b) // b is not defined

此時(shí),可以發(fā)現(xiàn)在內(nèi)部重新定義 b 的值并不會(huì)影響外部 b 的值。通過配合 let 使用,可以實(shí)現(xiàn)只在該塊級(jí)作用域內(nèi)實(shí)現(xiàn)變量的聲明。

let var 和 const

let
  1. let 的作用域在最近的 {} 之間
  2. 如果在 let a 之前使用 a 會(huì)報(bào)錯(cuò),即聲明前使用會(huì)報(bào)錯(cuò)
  3. 如果重復(fù) let a 會(huì)報(bào)錯(cuò),即重復(fù)聲明同一變量會(huì)報(bào)錯(cuò)
const

1.2.3. 同上

  1. 只有一次賦值機(jī)會(huì),而且必須在聲明時(shí)立即賦值

數(shù)組方法

forEach

在 ES5 中遍歷數(shù)組使用 for 循環(huán),但是 ES6 出現(xiàn)新的數(shù)組方法 forEach 方法

var colors=['red','green','black']
//ES6
colors.forEach(function(color){ //可以使用箭頭函數(shù)
  console.log(color)
})

使用場(chǎng)景:
-遍歷數(shù)組中的值,并計(jì)算求和

var list=[1,2,3,4]
var sum=0
function adder(number){
  sum +=number
}
list.forEach(adder) //也可以直接將求和函數(shù)放入其中

map

是將數(shù)組中的每一項(xiàng)做相同的函數(shù)處理,再返回。在 ES5 中需要使用到 for 循環(huán)將每一項(xiàng)做相同處理。
使用場(chǎng)景:

  • 將數(shù)組 A 中每一項(xiàng)乘以2,放入數(shù)組 B
var numbers=[1,2,3]
var double=[]
double=numbers.map(function(item){
  return item*2
})
  • 將對(duì)象數(shù)組 A 中的某一指定項(xiàng)存入到數(shù)組 B 中
var cars=[{
  model:'a',price:'cheap'
},{
  model:'b',price:'expensive'
}]
var prices=cars.map(function(item){
  return item.price
})

filter

返回?cái)?shù)組中指定項(xiàng)。(找到所有滿足條件的項(xiàng)
使用場(chǎng)景:

  • 返回對(duì)象數(shù)組 A 中指定項(xiàng)到數(shù)組 B 中
var porducts = [
  {name:"cucumber",type:"vegetable"},
  {name:"banana",type:"fruit"},
  {name:"celery",type:"vegetable"},
  {name:"orange",type:"fruit"}
]
var filter=porducts.filter(function(item){
  return item.type === 'fruit'
})
  • 可以在對(duì)象數(shù)組 A 中過濾掉不滿足條件的項(xiàng)
var products = [
  {name:"cucumber",type:"vegetable",quantity:0,price:1},
  {name:"banana",type:"fruit",quantity:10,price:16},
  {name:"celery",type:"vegetable",quantity:30,price:8},
  {name:"orange",type:"fruit",quantity:3,price:6}
]
var pros=products.filter(function(item){
  return item.type === 'fruit' && item.quantity > 5 && item.price >5 
})
  • 兩個(gè)數(shù)組 A 和 B ,根據(jù) A 中 id 過濾掉 B 中不符合項(xiàng)
var a = {id:4,title:"Javascript"}
var b = [
    {postId:4,content:"Angular4"},
    {postId:2,content:"Vue.js"},
    {postId:3,content:"Node.js"},
    {postId:4,content:"React.js"},
 ]
var c=b.filter(function(item){
  return item.postId === a.id
})

find

filter 方法類似,但是也不同。是找到符合條件的那一項(xiàng),就會(huì)停止(找到即停止)。

var users = [
  {name:"Jill"},
  {name:"Alex",id:2},
  {name:"Bill"},
  {name:"Alex"}
 ]
var user=users.find(function(item){
  return item.name === 'Alex'
})
console.log(user) //{name: "Alex", id: 2}

在上例中,只會(huì)返回帶有 id 的那一項(xiàng)(找到即停止

every & some

可以根據(jù)其英文意思來推斷它的作用。 every :每一個(gè)條件都要滿足(一真即真); some :滿足其一條件即可(一假即假)。
使用場(chǎng)景:

  • 用來判斷數(shù)組中每一項(xiàng)是否滿足某某條件
var computers = [
  {name:"Apple",ram:16},
  {name:"IBM",ram:4},
  {name:"Acer",ram:32}
]
var every=computers.every(function(item){
  return item.ram > 16
})
console.log(every) // false
var some=computers.some(function(item){
  return item.ram > 16
})
console.log(some) // true
  • 用于判斷表單中是否有數(shù)據(jù)(具體還需去除兩端空格等等)
 var username = "xxx"
 var telephone = "888"
 var password = "666"
 var fields = [username,telephone,password]
var p=fields.every(function(item){
  return item.length > 0
})

reduce

可以理解為減少,對(duì)累計(jì)器和數(shù)組中的每個(gè)元素(從左到右)應(yīng)用一個(gè)函數(shù),將其簡(jiǎn)化為單個(gè)值??梢詫?shí)現(xiàn)相加,將對(duì)象數(shù)組中的某一項(xiàng)抽離等。其中 reduce 方法中傳入四個(gè)參數(shù),acc (累計(jì)器)、cur (當(dāng)前值)、idx (當(dāng)前索引)、src (源數(shù)組)
使用場(chǎng)景:

  • 數(shù)組中每一項(xiàng)相加
var a=[1,2,3]
var b=a.reduce(function(sum,item){ // 第一個(gè)參數(shù)是累加的項(xiàng),第二個(gè)參數(shù)是源數(shù)組的項(xiàng)
  return sum += item
},0) // 此處的0表示 sum 的初始值
  • 將對(duì)象數(shù)組中的指定項(xiàng)抽離
 var primaryColors = [
   {color:"red",id:1},
   {color:"yellow",id:2},
   {color:"blue",id:3}
 ]
var colors=primaryColors.reduce(function(xxx,item){
  xxx.push(item.color) //先執(zhí)行每一項(xiàng)的push操作
  return xxx //返回的是執(zhí)行push操作后的數(shù)組
},[])
console.log(colors)
  • 用于判斷字符串中括號(hào)是否對(duì)稱(定義一個(gè)變量,遇到 ‘(’ 加1,遇到 ‘)’ 減1,通過判斷最后變量值確定是否對(duì)稱
function balancedParens(string){
  return !string.split("").reduce(function(x,item){ // 將字符串分隔為數(shù)組
    if(x<0){return x} // 判斷首項(xiàng)是否為 ‘)’ ,是直接返回
    if(item==='('){return ++x}
    if(item===')'){return --x}
    return x
  },0)
}
console.log(balancedParens(')()()(')) // false

模板字符串

在 ES5 中對(duì)于字符串的拼接需要使用 '' 與 + 的組合來實(shí)現(xiàn),而且不能在其中換行,只能使用拼接方式實(shí)現(xiàn)換行和變量的引入。
但是,在 ES6 中使用反引號(hào)實(shí)現(xiàn)模板字符串。其中還可以使用變量和方法等。

var name='Tony'
function toUp(wold){
  return wold.toUpperCase()
}
var string=`<h1>${toUp(hello)},${name}</h1>
<p>文本內(nèi)容</p>`;

箭頭函數(shù)

  1. 縮減代碼
  2. 改變 this 指向
  • 縮減代碼
    當(dāng)只有一個(gè)參數(shù)時(shí),括號(hào)可以省略
    當(dāng)只存在返回體時(shí),return 可省略,花括號(hào)也可以省略
    當(dāng)有多條語(yǔ)句時(shí),并且存在返回值時(shí),必須添加花括號(hào)和 return
var a=function(number){
  return number*2
}
// 可以使用箭頭函數(shù)
var a1= number => number*2
  • 改變 this 指向

在 ES5 中有兩種方法可以實(shí)現(xiàn)函數(shù)嵌套函數(shù)時(shí) this 指向問題,如下:

var team1={
  members : ['a','b'],
  teamName : 'C',
  teamSummary : function(){
    return this.members.map(function(item){
      return `成員${item}隸屬于${this.teamName}小組`
    })
  } 
}
console.log(team1.teamSummary()) //["成員a隸屬于undefined小組", "成員b隸屬于undefined小組"]

這樣雖然不會(huì)報(bào)錯(cuò),但是會(huì)出現(xiàn) undefined。這時(shí)我們需要在函數(shù)中使用變量存放外部 this 或者使用 bind 調(diào)用函數(shù)。

var team2={
  members : ['a','b'],
  teamName : 'C',
  teamSummary : function(){
    var self=this // 使用變量存放 this
    return this.members.map(function(item){
      return `成員${item}隸屬于${self.teamName}小組`
    })
  } 
}
/********************************************************/
var team3={
  members : ['a','b'],
  teamName : 'C',
  teamSummary : function(){
    return this.members.map(function(item){
      return `成員${item}隸屬于${this.teamName}小組`
    }.bind(this)) //使用 bind 傳入 this
  } 
}

但是,在 ES6 中可以使用箭頭函數(shù)改變 this 指向

var team4={
  members : ['a','b'],
  teamName : 'C',
  teamSummary : function(){
    return this.members.map(item=>`成員${item}隸屬于${this.teamName}小組`) 
//使用 箭頭函數(shù) 改變 this 的指向
  } 
}

總結(jié)箭頭函數(shù)的 this 指向是定義時(shí) this 的指向

var a=function (){
  this.b = 'b',
  this.c = 'c',
  this.d = {
    b : '+b',
    v : ()=>{return this.b}
  }
}
console.log(new a().d.v()) // b 

此時(shí),調(diào)用函數(shù)中的 v 函數(shù),this 指向是定義時(shí)的 this 指向。這里改為非箭頭函數(shù)得到的結(jié)果是 +b可以理解為箭頭函數(shù)不算定義函數(shù)的方式注意:這里調(diào)用時(shí),使用 new 方法,如果不使用 new 方法,是沒有 this 的。

增強(qiáng)對(duì)象字面量

  1. 當(dāng)對(duì)象的“鍵”和“值”相同的情況下可以省略,只寫一個(gè)
  2. 當(dāng)對(duì)象中有方法時(shí): :function 可以省略
function createShop(list){
  return {
    list, // list:list
    listValue(){ //省略 :function
      return this.list.reduce((sum,item)=>{return sum += item.price},0)
    },
    priceForTitle(title){
      return this.list.find(item=>item.title === title).price
    }
  }
}
var bookList= [
  {title:"Vue",price:10},
  {title:"Angular",price:15}
]
var bookShop = createShop(bookList)
console.log(bookShop.listValue())
console.log(bookShop.priceForTitle("Angular"))

函數(shù)參數(shù)默認(rèn)值

在 ES6 中可以設(shè)置函數(shù)參數(shù)的默認(rèn)值,通過以下方式:

function a(b,c=3){
  return c
}
console.log(a(1)) // 3
console.log(a(1,2))  //2

可以看出第一個(gè)輸出的情況下,并沒有傳入第二個(gè)參數(shù) c 但是第二個(gè)參數(shù)通過 c=3 傳入一個(gè)默認(rèn)值 3 。第二個(gè)輸出的情況下,傳入第二個(gè)參數(shù),所以 a 函數(shù)中第二個(gè)參數(shù)的默認(rèn)參數(shù)失效。

展開運(yùn)算符

可以在函數(shù)調(diào)用/數(shù)組構(gòu)造時(shí), 將數(shù)組表達(dá)式或者 string 在語(yǔ)法層面展開;還可以在構(gòu)造字面量對(duì)象時(shí), 將對(duì)象表達(dá)式按key-value的方式展開。(譯者注: 字面量一般指 [1, 2, 3] 或者 {name: "mdn"} 這種簡(jiǎn)潔的構(gòu)造方式)

function add(number){
  return number.reduce((sum,item)=>{
    return sum += item
},0)
}
console.log(add([1,2,3]))

使用展開運(yùn)算符進(jìn)行操作,就簡(jiǎn)單很多。

function add(...number){
  return number.reduce((sum,item)=>{
    return sum += item
},0)
}
console.log(add(1,2,3,4,5,6))

同時(shí),展開運(yùn)算符的方式等同于 apply 的方式(但是通過 new 方式構(gòu)造的函數(shù)不適用):

function add(x,y,z){
  return x+y+z
}
console.log(add.apply(null,[1,2,3]))

還可以通過展開語(yǔ)法實(shí)現(xiàn)數(shù)組的拼接與復(fù)制等。

//數(shù)組拼接
var a = ['1' , '3']
var b = ['0' , ...a , '4' , '5'] // ["0", "1", "3", "4", "5"]

// 數(shù)組復(fù)制
var c = [6 , 7]
var d = [...c] // [6 , 7]
d.push(8) // [6 , 7 , 8]
console.log(c) // [6 , 7] 可得出通過展開運(yùn)算復(fù)制的數(shù)組,不影響源數(shù)組

// 還可以實(shí)現(xiàn)不同位置的拼接,達(dá)到 unshift 的方法
var e = [...c , ...a] // [6, 7, "1", "3"]

解構(gòu)賦值

解構(gòu)賦值語(yǔ)法是一個(gè) Javascript 表達(dá)式,這使得可以將值從數(shù)組屬性從對(duì)象提取到不同的變量中。

特點(diǎn):更快,更便捷。
結(jié)構(gòu)復(fù)制可以是數(shù)組,也可以是對(duì)象

  • 對(duì)象
    在 ES5 中,實(shí)現(xiàn)方法。
var img = {
  extension: "jpg",
  name:"girl",
  size:14040
}
// es5
function imgSummary(file){
  return `${file.name}.${file.extension}的尺寸為${file.size}`
}
console.log(imgSummary(img)) //girl.jpg的尺寸為14040

但是在 ES6 中可以使用解構(gòu)賦值的方式實(shí)現(xiàn)該方法

function imgSummary({name,extension,size}){
  return `${name}.${extension}的尺寸為${size}`
}

上述方法中可以看做 {name,extension,size}=img 等同于 name=img.name extension=img.extension size=img.size 這三行代碼。

  • 數(shù)組
    在數(shù)組的解構(gòu)賦值中:當(dāng)解構(gòu)個(gè)數(shù)等于數(shù)組的項(xiàng)數(shù)時(shí),可得到數(shù)組每一項(xiàng);當(dāng)不等于時(shí),會(huì)得到從左邊開始解構(gòu)個(gè)數(shù);當(dāng)只有一個(gè)值并且以 {} 包住時(shí),返回數(shù)組個(gè)數(shù)
var list = ['a' , 'b' , 'c']
// 返回全部數(shù)組
var [name1,name2,name3] = list
console.log(name1,name2,name3) // 'a' 'b' 'c'

// 返回需要個(gè)數(shù)
var [name4,name5] = list
console.log(name4,name5) // 'a' 'c' 

// 返回?cái)?shù)組個(gè)數(shù)
var {length} = list
console.log(length) // 3

還可以結(jié)合展開運(yùn)算符,使用了展開運(yùn)算的存放剩下的數(shù)組。

var [name6 , ...rest] = list
console.log(name6) // 'a'
console.log(rest) // ["b", "c"]
  • 對(duì)象數(shù)組
var people = [
  {name:'a',age:15},
  {name:'b',age:20},
  {name:'c',age:25}
]
// es5 取其中某一項(xiàng)的 age
var age = people[0].age
// es6 中取某一項(xiàng)的age 使用 [] 取到項(xiàng),在使用 {} 結(jié)構(gòu)到具體某一項(xiàng)
var [{age}] = people 

上述,先使用數(shù)組的解構(gòu)得到第一項(xiàng),在使用對(duì)象的解構(gòu)得到需要的項(xiàng)。

  • 使用場(chǎng)景:將數(shù)組轉(zhuǎn)換為對(duì)象
var points = [
  [4,5],
  [10,1],
  [0,40]
]
// 期待格式
[
  {x:4,y:5},
  {x:10,y:1},
  {x:0,y:40}
]
// es6 解構(gòu)賦值
var newPoint = points.map(([x,y])=>{
  return {x,y}
})

面向?qū)ο螅╟lass)

ES5 有很多方法實(shí)現(xiàn)繼承

// 定義 Car 
function Car(options) { 
  this.title=options.title
}
// 定義 Car 的方法
Car.prototype.drive=function(){return 'move'}
// new 一個(gè) Car
var car = new Car({title:'BMW'})
// 重新定義一個(gè)車的品牌,并繼承 Car 的p品牌和行為
function Toyota (options){
  Car.call(this,options) // 通過call調(diào)用Car實(shí)現(xiàn)title的繼承
  this.color=options.color
}
// 實(shí)現(xiàn)方法的繼承
Toyota.prototype=Object.create(Car.prototype) // 通過Object.create創(chuàng)建一個(gè)函數(shù)指向Car
Toyota.constructor=Toyota // Toyota的構(gòu)造函數(shù)指向Toyota(可不加)
var toyota=new Toyota({title:'Toyota ',color:'red'})

這樣就是在 ES5 通過 Object.create() 實(shí)現(xiàn)繼承,這時(shí) toyota 擁有 title color 屬性和 drive 方法。注:這種方法有兼容性的問題,低版本瀏覽器可能不兼容
但是,在 ES6 中只需要使用 extends 配合 super 實(shí)現(xiàn)繼承

class Car{
  constructor({title}){
    this.title=title
  }
  drive(){
    return 'move'
  }
}
// Toyota 只需要使用 extends 關(guān)鍵字
class Toyota extends Car {
  constructor(options){
    super(options)
    this.color=options.color
  }
}

在 ES6 中構(gòu)造器函數(shù)(constructor)定義對(duì)象的屬性,然后在定義其方法(不加逗號(hào))。

generator生成器

生成器對(duì)象是由一個(gè) generator function 返回的,并且它符合可迭代協(xié)議和迭代器協(xié)議。

簡(jiǎn)單說:可以返回多次函數(shù),類似于迭代器函數(shù)

function* number(){
  yield 1
  yield 2
}
var n=number()
console.log(n.next()) // {value: 1, done: false}
console.log(n.next()) // {value: 2, done: false}
console.log(n.next()) // {value: undefined, done: true}

如上所述:在 function 后添加 * 號(hào)既是 generator 生成器。在 generator 生成器中有 yield 可以返回相應(yīng)的值,格式是 key-value 。當(dāng)超出數(shù)量再次調(diào)用時(shí),如上。

  • 使用 generator 生成器完成斐波那契數(shù)列
function* fib(max){
  var a=0,b=1,n=0
  while(n<max){
    yield a;
    [a,b]=[b,a+b];
    n++;
  }
  return
}
for (var x of fib(5)){ // 這里使用for-of循環(huán)可便利出fib函數(shù)的next方法中的value
  console.log(x)
}

注意:在 yield 后必須加分號(hào),否則會(huì)出 bug

  • 使用迭代器還原 generator 生成器的結(jié)構(gòu)
function number(numbers){
  let nextIndex=0
  return {
    next:function(){
      return nextIndex < numbers.length?
                 {value:numbers[nextIndex++],done:false}:
                 {value:undefined,done:true}
    }
  }
}
var n=[1,2]
var ns=number(n)
console.log(ns.next()) // {value: 1, done: false}
console.log(ns.next()) // {value: 2, done: false}
console.log(ns.next()) // {value: undefined, done: true}

在實(shí)際應(yīng)用場(chǎng)景中,可以應(yīng)用到 id自增器

新的數(shù)據(jù)結(jié)構(gòu)

數(shù)據(jù)結(jié)構(gòu):map

鍵值對(duì):與對(duì)象不同的是鍵和值都可以是任意數(shù)據(jù)類型

var map1=new Map()
// 設(shè)置 key 值
var key1='string',
key2={},
key3=function(){}
// 使用set設(shè)置value值
map1.set(key1,'Value of key1')
map1.set(key2,'Value of key2')
map1.set(key3,'Value of key3')
// 使用for-of遍歷key值(結(jié)合keys方法)
for(let key of map1.keys()){
  console.log(key) // string  {}  ? (){}
}
//使用set獲取value值
console.log(map1.get(key1)) // Value of key1
//使用size獲取數(shù)據(jù)數(shù)量
console.log(map1.size) // 3

數(shù)據(jù)結(jié)構(gòu):set

集合:可以儲(chǔ)存任意數(shù)據(jù)類型,并且是唯一的(不重復(fù))

var set1=new Set()
// 使用add方法向set1添加數(shù)據(jù)
set1.add(100)
set1.add('string')
set1.add({a:'b'})
set1.add(true)
set1.add(100) // 重復(fù)數(shù)據(jù),不會(huì)再set1中顯示,且不占位置
console.log(set1) //{100, "string", {…}, true}
// 使用size計(jì)算數(shù)據(jù)數(shù)量
console.log(set1.size) // 4
// 使用has方法判斷set1是否有該數(shù)據(jù)
console.log(set1.has(100)) // true
console.log(set1.has(50+50)) // true
console.log(set1.has({a:'b'})) // false 由于對(duì)象是引用類型,地址不同所以這里是false
// 使用delete方法刪除某一數(shù)據(jù)
set1.delete(100) 
console.log(set1) // {"string", {…}, true}
// 使用for-of遍歷數(shù)據(jù)
for(let item of set1){
  console.log(set1) // 打印三遍{"string", {…}, true}
}

新的數(shù)據(jù)結(jié)構(gòu)總結(jié)

因?yàn)椋@兩個(gè)新數(shù)據(jù)結(jié)構(gòu)都是類數(shù)組類型,都可以使用 forEach 方法遍歷。
并且都可以使用數(shù)組的新方法 from 使類數(shù)組結(jié)構(gòu)轉(zhuǎn)換為數(shù)組結(jié)構(gòu)。

var map2=Array.from(map1)
var set2=Array.from(set1)
console.log(map2) //[["string", "Value of key1"], [{…}, "Value of key2"], [?, "Value of key3"]]
console.log(set2) // [100, "string", {…}, true]

同時(shí),由于 new Set() 數(shù)據(jù)結(jié)構(gòu)中數(shù)據(jù)的不重復(fù)性,所以可以用來實(shí)現(xiàn)數(shù)組去重

var a=[1,1,1,2,3,4,5,3,2]
var b=Array.from(new Set(a))
console.log(b) // [1, 2, 3, 4, 5]

promise

Promise 對(duì)象用于表示一個(gè)異步操作的最終狀態(tài)(完成或失?。约捌浞祷氐闹?。
Promise 返回的是一個(gè)函數(shù),所以需要使用 .then() 使用。即是鏈?zhǔn)讲僮鳌?br> 一個(gè)promise可能有三種狀態(tài):等待(pending)、已完成(fulfilled)、已拒絕(rejected)。

  • 已完成 Fulfilled
    resolve 成功時(shí),調(diào)用 onFulfilled
  • 已拒絕 Rejected
    reject 失敗時(shí),調(diào)用 onReject
  • 等待 Pending
    既不是成功(resolve)也不是失?。?code>reject),而是在promise函數(shù)創(chuàng)建后的初始狀態(tài)
let promise=new Promise((resolve,reject)=>{
  resolve()
  //reject()
})
promise.then(()=>console.log('成功1'))
    .then(()=>console.log('成功2'))
    .catch(()=>console.log('失敗'))

當(dāng)上述代碼中存在 resolve() 且執(zhí)行時(shí),在控制臺(tái)會(huì)打印出‘成功1’和‘成功2’。當(dāng)存在 reject() 且執(zhí)行時(shí),控制臺(tái)會(huì)打印出‘失敗’。



在沒有 promise 對(duì)象的 ES5 中使用回調(diào)函數(shù)實(shí)現(xiàn)。

Promise.all() 可以集中處理多個(gè)異步

Promise.all()生成的是一個(gè)新的Promise實(shí)例。成功和失敗返回值不同,成功時(shí)返回的是成功的數(shù)組,失敗時(shí)只要有一個(gè)失敗,就會(huì)返回最先失敗的結(jié)果
其執(zhí)行順序與傳入到 Promise.all() 的數(shù)組的順序一致

Promise.all(iterable) 方法返回一個(gè) Promise 實(shí)例,此實(shí)例在 iterable 參數(shù)內(nèi)所有的 promise 都“完成(resolved)”或參數(shù)中不包含 promise 時(shí)回調(diào)完成(resolve);如果參數(shù)中 promise 有一個(gè)失?。╮ejected),此實(shí)例回調(diào)失敗(reject),失敗原因的是第一個(gè)失敗 promise 的結(jié)果。

簡(jiǎn)單的說:就是將代碼中所有的 Promise 對(duì)象以數(shù)組的形式放在 Promise.all(iterable) 中(即是 iterable),將 all 中所有的異步執(zhí)行完畢后才會(huì)去執(zhí)行 Promise.all(iterable) 后的 .then() 方法,但是如果有一個(gè)失敗則次實(shí)例回調(diào)失敗。

var p1=Promise.resolve(1)
var p2=Promise.resolve(2)
var p3=Promise.resolve(3)
Promise.all([p1,p2,p3]).then(val=>console.log(val)).catch(()=>console.log('error')) // [1,2,3]
// 當(dāng)其中有一個(gè)執(zhí)行了reject函數(shù)
var p4=Promise.resolve(4)
var p5=Promise.reject(5)
var p6=Promise.resolve(6)
Promise.all([p4,p5,p6]).then(val=>console.log(val)).catch(()=>console.log('error')) // error

注:如果 Promise.all() 中有多個(gè)異步執(zhí)行,最終返回的事件按照延時(shí)最長(zhǎng)的計(jì)算。

有關(guān)于Promise試題

關(guān)于數(shù)據(jù)請(qǐng)求的新API fetch (ES7)

fetch 是在 ES7 出現(xiàn)的新的關(guān)于實(shí)現(xiàn)數(shù)據(jù)請(qǐng)求的 API 。傳統(tǒng)情況下,一般使用 XHRXMLHttpRequest) 瀏覽器的原生 API 實(shí)現(xiàn)或者使用 jQuery 封裝的 AJAX(異步的JS請(qǐng)求)。
現(xiàn)在出現(xiàn)了新的瀏覽器原生 API fetch 可以實(shí)現(xiàn)數(shù)據(jù)請(qǐng)求。基于Promise,更簡(jiǎn)單,更便捷。

Fetch API 提供了一個(gè)獲取資源的接口(包括跨域)。

因?yàn)?fetch() 得到的是 Promise 的 pending 狀態(tài),.then() 得到的是Response對(duì)象,所以需要再 .then() 。一般情況下都需要兩次

let url = "http://jsonplaceholder.typicode.com/posts"
fetch(url) // 獲得的是promise的pending 等待任務(wù)完成
  .then(res=>res.json()) // 得到的是Response對(duì)象,需要進(jìn)行json解析
  .then(data=>console.log(data)) // [{…}, {…},.....,{…}, {…}]
  .catch(error=>console.log(error)) // 如果出錯(cuò)會(huì)打印出錯(cuò)誤

注:如果是返回狀態(tài)碼大于300,都不會(huì)打印出錯(cuò)誤,只會(huì)在控制臺(tái)提示;只有狀態(tài)碼300以下的才會(huì)打印出錯(cuò)誤

let url = "http://jsonplaceholder.typicode.com/posts123" // 這里更改
fetch(url) // 獲得的是promise的pending 等待任務(wù)完成
  .then(res=>res.json()) // 得到的是Response對(duì)象,需要進(jìn)行json解析
  .then(data=>console.log(data)) // [{…}, {…},.....,{…}, {…}]
  .catch(error=>console.log(error)) // 如果出錯(cuò)會(huì)打印出錯(cuò)誤

如果是下邊一種情況,在請(qǐng)求域名出現(xiàn)問題:

let url = "http://jsonplaceholder.typicode123.com/posts" // 這里更改
fetch(url) // 獲得的是promise的pending 等待任務(wù)完成
  .then(res=>res.json()) // 得到的是Response對(duì)象,需要進(jìn)行json解析
  .then(data=>console.log(data)) // [{…}, {…},.....,{…}, {…}]
  .catch(error=>console.log('錯(cuò)誤:'+ error)) // 如果出錯(cuò)會(huì)打印出錯(cuò)誤

fetch() 可以請(qǐng)求三種數(shù)據(jù)格式:本地 text 數(shù)據(jù)、本地 json 數(shù)據(jù)、網(wǎng)絡(luò) api 數(shù)據(jù)。(都是使用兩次 .then() 得到數(shù)據(jù))
參考文章:傳統(tǒng) Ajax 已死,F(xiàn)etch 永生
參考文章: fetch,終于認(rèn)識(shí)你

async & await (ES7)

async 關(guān)鍵字放置在函數(shù)的前面,確保函數(shù)返回的是 Promise 對(duì)象。如果代碼中有 return <非promise> 語(yǔ)句,JavaScript會(huì)自動(dòng)把返回的這個(gè)value值包裝成promise的resolved值。

async function time(){
  return 'hello'
}
console.log(time()) // Promise {<resolved>: "hello"}

await 關(guān)鍵字在函數(shù)內(nèi)部使用,async 函數(shù)返回的 Promise 對(duì)象,必須等到內(nèi)部所有的 await 命令的 Promise 對(duì)象執(zhí)行完,才會(huì)發(fā)生狀態(tài)改變

當(dāng)函數(shù)內(nèi)部有 await 關(guān)鍵字時(shí),會(huì)等待執(zhí)行完成后,再去執(zhí)行后邊的函數(shù)

可以看到有 async 關(guān)鍵字的函數(shù)返回的是 Promise 對(duì)象,并且雖然其先執(zhí)行,但是先打印出了‘1’,說明其是異步的。
正常情況下,await 命令后面跟著的是 Promise ,如果不是的話,也會(huì)被轉(zhuǎn)換成一個(gè) 立即 resolvePromise

async function time(){
    return await 1
}
time().then(val=>console.log(val)) // 1

注意:await 不能在頂級(jí)作用域(即不能直接跟 fetch(url) ,需要在包裹在 async 函數(shù)內(nèi))

封裝 fetch 庫(kù)實(shí)現(xiàn)增刪改查(使用async/await簡(jiǎn)化代碼)

定義一個(gè)類,使用 fetch 獲取數(shù)據(jù),并返回一個(gè) Promise 對(duì)象

class Http{
    // get 請(qǐng)求
    get(url){
        return new Promise((resolve,reject)=>{
            fetch(url)
                  .then(res=>res.json()) // 將得到的數(shù)據(jù)轉(zhuǎn)為可讀的json數(shù)據(jù)
                  .then(data=>resolve(data)) // 成功函數(shù)
                  .catch(error=>reject(error)) // 失敗函數(shù)
        })
    }
    // post 請(qǐng)求
    post(url,data){
        return new Promise((resolve,reject)=>{
            fetch(url,{ // fetch 的第二個(gè)參數(shù)
                method:'POST', // 定義請(qǐng)求方式
                headers:{ // 定義請(qǐng)求頭
                    'Content-type':'application/json'
                },
                body:JSON.stringify(data) // 定義第四部分的格式
            })
              .then(res=>res.json())
              .then(data=>resolve(data))
              .catch(error=>reject(error))
        })
   }
// put 和 delete 請(qǐng)求類似于 post 請(qǐng)求,delete請(qǐng)求沒有第四部分
}
// 使用該庫(kù)
let http=new Http
http.get('http://jsonplaceholder.typicode.com/users')
.then(data=>console.log(data))
使用 async/await 簡(jiǎn)化代碼
class Http{
    // get 請(qǐng)求
    async get(url){
        let response=await fetch(url)
        let resData=await response.json()
        return resData
    }
    // post 請(qǐng)求
    async post(url,data){
        let response=await fetch(url,{ // fetch 的第二個(gè)參數(shù)
                method:'POST', // 定義請(qǐng)求方式
                headers:{ // 定義請(qǐng)求頭
                    'Content-type':'application/json'
                },
                body:JSON.stringify(data) // 定義第四部分的格式
            })
        let resData=await response.json()
        return resData
   }
// put 和 delete 請(qǐng)求類似于 post 請(qǐng)求,delete請(qǐng)求沒有第四部分
}
// 使用該庫(kù)
let http=new Http
http.get('http://jsonplaceholder.typicode.com/users')
.then(data=>console.log(data))

async/await 的引入是代碼更加簡(jiǎn)潔和易讀

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容