常量
- 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
- let 的作用域在最近的 {} 之間
- 如果在 let a 之前使用 a 會(huì)報(bào)錯(cuò),即聲明前使用會(huì)報(bào)錯(cuò)
- 如果重復(fù) let a 會(huì)報(bào)錯(cuò),即重復(fù)聲明同一變量會(huì)報(bào)錯(cuò)
const
1.2.3. 同上
- 只有一次賦值機(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ù)
- 縮減代碼
- 改變 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ì)象字面量
- 當(dāng)對(duì)象的“鍵”和“值”相同的情況下可以省略,只寫一個(gè)
- 當(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)于數(shù)據(jù)請(qǐng)求的新API fetch (ES7)
fetch 是在 ES7 出現(xiàn)的新的關(guān)于實(shí)現(xiàn)數(shù)據(jù)請(qǐng)求的 API 。傳統(tǒng)情況下,一般使用 XHR(XMLHttpRequest) 瀏覽器的原生 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è) 立即 resolve 的 Promise
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)潔和易讀
