區別實例對象與函數對象html
一、實例對象:new 函數產生的對象,稱爲實例對象,簡稱對象python
二、函數對象:將函數做爲對象使用時,簡稱函數對象web
<script> function Fn(){//Fn函數 } const fn = new Fn() //Fn是構造函數,fn是實例對象(簡稱對象) console.log(Fn.prototype)//Fn是函數對象 Fn.bind({})//調用函數對象的bind方法 $("#test") //jQuery函數 $.get("/test") //jQuery函數對象,括號左邊是函數,點的左邊是對象 </script>
兩種類型的回調函數ajax
回調函數:回調函數就是一個參數,將這個函數做爲參數傳到另外一個函數裏面,當那個函數執行完以後,再執行傳進去的這個函數。這個過程就叫作回調編程
同步回調數組
理解:當即執行,徹底執行完了才結束,不會放入到回調隊列中promise
例子:數組遍歷相關的回調函數,Promise的excutor函數異步
異步回調async
理解:不會當即執行,會放入到隊列中未來執行異步編程
例子:定時器回調、ajax、Promise的成功|失敗的回調
<script> //一、同步回調函數 const arr = [1,2,3] arr.forEach((item) =>{//遍歷回調函數,同步回調函數,不會放入隊列,一上來就要執行完 console.log(item) }) console.log("forEach函數以後") //二、異步回調函數 setTimeout(() => {//異步回調函數,會放入隊列中未來執行 console.log("timeout callback()") }, 0) console.log("setTimeout函數以後")//先於setTimeout的回調函數執行 </script>
JS中的error處理
一、錯誤的類型
一、Error:全部錯誤的父類型
二、ReferenceError:引用的變量不存在
三、TypeError:數據類型不正確的錯誤
四、RangeError:數據值再也不其容許的範圍內
五、SyntaxError:語法錯誤
二、錯誤處理
一、捕獲錯誤:try ... catch
二、拋出錯誤:throw error
三、錯誤對象
message屬性:錯誤相關信息
stack屬性:函數調用棧記錄信息
<script> //一、常見的內置錯誤 //console.log(aaa) //ReferenceError: aaa is not defined console.log("----")//沒有捕獲error,下面的代碼不會執行 let b = null //console.log(b.xx) //TypeError: b is null // function fn(){ // fn() // } // fn() //RangeError: Maximum call stack size exceeded const c = """" //SyntaxError: unexpected token: string literal
//二、錯誤處理
try{
let d
console.log(d.xxx)
}catch(error){
console.log(error.message)//d is undefined
console.log(error.stack)// @file:///home/xdl/python/web/day01/code/01_html.html:71:3
}
console.log("出錯以後")//能夠正常執行
//拋出異常
function something(){
if(Date.now()%2===1){
console.log("當前時間爲奇數,能夠執行任務")
}else{//若是時間爲偶數拋出異常,由調用者來處理
throw new Error("當前時間爲偶數,沒法執行任務")
}
}
try{
something()
}catch(error){
console.log(error.message)//當前時間爲偶數,沒法執行任務
} </script>
promise的理解和使用
一、promise是什麼?
理解:
一、抽象表達:promise是JS中進行異步編程的新的解決方案(以前是純回調的方式)
二、具體表達:
一、從語法上來講:promise是一個構造函數
二、從功能上來講:promise對象用來封裝一個異步操做並能夠獲取其結果
promise的狀態改變:
一、pedding變爲resolved
二、pedding變爲rejected
說明:只有這兩種,且一個promise對象只能改變一次,不管變爲成功仍是失敗,都會有一個結果數據,成功的結果數據通常稱爲value,失敗的結果數據通常稱爲reason
promise的基本使用
<script> //一、建立一個新的promise對象 const p = new Promise((resolve, reject) => {//執行器函數,同步回調 //二、執行異步任務 setTimeout(() => { const time = Date.now() //若是當前時間是偶數表明成功,不然表明失敗 if (time % 2 === 0){ //3.一、若是成功,調用resolve(value) resolve("成功的數據,time=" + time) }else{ //3.二、若是失敗,調用reject(reason) reject("失敗的數據,time=" + time) } },1000) }) p.then( (value) => {//接收穫得成功的value數據,onResolved console.log("成功的回調", value) }, (reason) => {//接收穫得失敗的reason數據, onRejected console.log("失敗的回調", reason) } ) </script>
二、爲何要使用promise
一、指定回調函數的方式更加靈活:
舊的:必須在啓動異步任務前指定
promise:啓動異步任務 => 返回promise對象=>給promise對象綁定回調函數(甚至能夠在異步執行完成以後)
二、支持鏈式調用,能夠解決回調地獄問題
什麼是地獄問題?回調函數嵌套調用,外部回調函數異步執行的結果是嵌套的回調函數執行的條件
回調地獄的缺點?不便於閱讀,不便於異常處理
解決方案?promise鏈式調用
終極解決方案?async、await
三、如何使用promise
API
一、Promise構造函數:Promise(excutor){}
excutor函數:同步執行(resolve, reject)=> {}
reslove函數:內部定義成功時咱們調用的函數value=>{}
reject函數:內部定義失敗時咱們調用的函數 reason=>{}
說明:excutor會在promise內部當即同步回調,異步操做在執行器中執行
二、Promise.prototype.then方法:(onResolved, onRejected)=>{}
onResolved函數:成功的回調函數 (value)=>{}
onRejected函數:失敗的回調函數(reason)=>{}
說明:指定用於獲得成功value的成功回調和用於獲得失敗reason的失敗回調,返回一個新的promise對象
三、Promise.prototype.catch方法:(onRejected)=>{}
onRejected函數:失敗的回調函數(reason)=>{}
說明:then()的語法糖,至關於:then(undefined,onRejected)
new Promise((resolve, reject) =>{ setTimeout(()=>{ resolve("成功的數據") //reject("失敗的數據") // 只會執行第一個 }, 1000) }).then( (value) => { console.log("onReaolved()1",value) } ).catch( (reason) => { console.log("onRejected()1", reason) } )
四、Promise.resolve方法:(value)=> {}
value:成功的數據或promise對象
說明:返回一個成功或失敗的promise對象
五、Promise.reject方法:(reason)=>{}
reason:失敗緣由
說明:返回一個失敗的promise對象
/產生一個成功值爲1的promise對象 const p1 = new Promise((resolve, reject)=>{ resolve(1) }) const p2 = Promise.resolve(2) const p3 = Promise.reject(3) p1.then(value=>{console.log(value)}) p2.then(value=>{console.log(value)}) p3.then( null, reason=>{console.log(reason)}) p3.catch(reason=>{console.log(reason)})
六、Promise.all方法:(promise)=>{}
promise:包含n和promise的數組
說明:返回一個新的promise,只有全部的promise都成功才成功,只要有一個失敗了就直接失敗
const p1 = new Promise((resolve, reject)=>{ resolve(1) }) const p2 = Promise.resolve(2) const p3 = Promise.reject(3) const pAll = Promise.all([p1,p2,p3]) pAll.then( values => { console.log("all onResolved()", values)//若是成功將返回一個數組 }, reason =>{ console.log("all onRejected()", reason)//3 } )
七、Promise.race方法:(promise)=>{}
promise:包含n和promise的數組
說明:返回一個新的promise,第一個完成的promise的結果狀態就是最終的結果狀態
//產生一個成功值爲1的promise對象 const p1 = new Promise((resolve, reject)=>{ setTimeout(()=>{ resolve(1) }) }) const p2 = Promise.resolve(2) const p3 = Promise.reject(3) const pRace = Promise.race([p1,p2,p3]) pRace.then( value => { console.log("race onResolved()", value) }, reason =>{ console.log("race onRejected()", reason) } )
promise的關鍵問題
一、如何改變Promise的狀態
一、resolve(value):若是當前是pedding就會變爲resolved
二、reject(reason):若是當前是pedding就會變爲rejected
三、拋出異常:若是當前狀態是pedding就會變爲rejeceted
const p = new Promise((resolve, reject) =>{ //resolve(1)//promies變爲resolved成功狀態 //reject(2)//promise變爲rejected失敗狀態 //throw new Error("出錯了")//拋出異常promise變爲rejected失敗狀態,reason 爲拋出的error throw 3 }); p.then( reason => {console.log("reason:", reason)}//3 )
二、一個promise指定多個成功或失敗回調函數,都會調用嗎?
當promise改變爲對應狀態時都會調用
const p = new Promise((resolve, reject) =>{ resolve(1) }); p.then( value => {console.log("value1:", value)}//value1: 1 ) p.then( value => {console.log("value2:", value)}//value2: 1 )
三、改變promise狀態和指定回調函數誰先誰後?
一、都有可能,正常狀況下時先指定回調函數再改變狀態,但也能夠先改變狀態再指定回調函數
二、如何先改變狀態再指定回調?
一、在執行器中直接調用resolve()/reject()
二、延遲更長時間才調用then()
//如何先改變狀態,後指定回調函數 new Promise((resolve, reject) =>{ reject(1)//先改變的狀態(同時指定數據) }).then(//後指定回調函數,異步執行回調函數 value => {console.log("value:", value)}, reason => {console.log("reason:", reason)} )
三、何時才能獲得數據?
一、若是先指定回調,那麼狀態發生改變時,回調函數就會調用,獲得數據
二、若是先改變的狀態,那麼指定回調時,回調函數就會調用,獲得數據
new Promise((resolve, reject) =>{ setTimeout(()=>{ resolve(1)//後改變的狀態(同時指定數據),異步執行回調函數 }, 1000) }).then(//先指定回調函數,保存當前指定的回調函數 value => {console.log("value1:", value)}//value1: 1 )
四、promise.then()返回的新的promise的結果狀態由什麼決定?
一、簡單表達:由then()指定的回調函數執行的結果決定
二、詳細表達:
一、若是拋出異常,新promise變爲rejected,reason爲拋出的異常
二、若是返回的是非promise的任意值,新的promise變爲resolved,value爲返回的值
三、若是返回的是另外一個新promise,此promise的結果就會成爲新promise的結果
new Promise((resolve, reject) =>{ resolve(1) //reject(1) }).then( value => { console.log("onResolved1():", value) //return 2 //return Promise.resolve(3) //return Promise.reject(4) throw 5 }, reason => { console.log("onRejected1():", reason) } ).then( value => { console.log("onResolved2():", value) }, reason => { console.log("onRejected2():", reason) } )
五、promise如何串連多個操做任務
一、promise的then()返回一個新的promise,能夠當作then()的鏈式調用
二、經過then的鏈式調用串連多個同步/異步任務
new Promise((resolve, reject) =>{ setTimeout(()=>{ console.log("執行任務1(異步)") resolve(1) },1000); }).then( value => { console.log("任務1的結果:", value) console.log("執行任務2(同步):") return 2 } ).then( value => { console.log("任務2的結果():", value) return new Promise((resolve, reject)=>{ setTimeout(()=>{ console.log("執行任務3(異步)") resolve(3) },1000) }) } ).then( value => { console.log("任務3的結果", value) } )
六、promise異常傳透?
一、當使用promise的then鏈式調用時,能夠在最後指定失敗的回調
二、前面任何操做出了異常,都會傳到最後失敗的回調中處理
new Promise((resolve, reject) =>{ resolve(1) //reject(1) }).then( value => { console.log("onResolveed1():", value) return Promise.reject(2) } ).then( value => { console.log("onResolveed2():", value) return 3 } ).then( value => { console.log("onResolveed3()", value) } ).catch(reason => { console.log("onRejected1()", reason) })
七、中斷promise鏈?
一、當時用promise的then的鏈式調用時,在中間中斷,再也不調用後面的回調函數
二、辦法:在回調函數中返回一個pedding狀態的promise對象
new Promise((resolve, reject) =>{ resolve(1) //reject(1) }).then( value => { console.log("onResolveed1():", value) return Promise.reject(2) } ).then( value => { console.log("onResolveed2():", value) return 3 } ).then( value => { console.log("onResolveed3()", value) } ).catch(reason => { console.log("onRejected1()", reason) return new Promise(()=>{})//返回一個pedding狀態的promise對象,中斷promise鏈 }).then( value => { console.log("onResolved4", value) }, reason => { console.log("onRejected2()", reason) } )
async與await
async函數
一、函數的返回值爲promise對象
二、promise對象的結果由async函數執行的返回值決定
// async函數的返回值是一個promise對象 //asyn函數返回的promise的結果由函數執行的結果決定 async function fn1(){ //return 1 throw 2 } const res = fn1() console.log(res) res.then( value =>{ console.log("onResolved", value) }, reason => { console.log("onRejected",reason) } )
await表達式
一、await右側的表達式通常爲promise對象,但也能夠是其餘的值
二、若是表達式是promise對象,await返回的是promise成功的值
三、若是表達式是其餘值,直接將此值做爲await的返回值
function fn2(){ return Promise.resolve(2) } async function fn3(){ //const value = await fn2() // await右側表達式爲promise,獲得的結果就是promise成功的value const value = await 6 //await右側表達式不是Promis,獲得的結果就是它本省 console.log("value:",value) } fn3()
注意:
await必須寫在async函數中,可是async函數中能夠沒有await
若是await的promise失敗了,就會拋出異常,須要經過try...catch來捕獲處理
JS異步之宏隊列與微隊列
一、JS中用來存儲執行回調函數的隊列包含2個不一樣特定的隊列
二、宏隊列:用來保存帶執行的宏任務,好比:定時器回調,DOM事件回調,ajax回調
三、微隊列:用來保存待執行的微任務,好比:promise的回調,MutationObserver的回調
四、JS執行時會區別這2兩個隊列
一、JS引擎首先必須先執行全部的初始化同步任務代碼
二、每次準備取出第一個宏任務前,都要講全部的微任務一個一個取出來執行