JS中的回調(diào)函數(shù)(callback)講解
1.什么是回調(diào)函數(shù)(callback)呢?
把函數(shù)當作一個參數(shù)傳到另外一個函數(shù)中,當需要用這個函數(shù)是,再回調(diào)運行()這個函數(shù).
回調(diào)函數(shù)是一段可執(zhí)行的代碼段,它作為一個參數(shù)傳遞給其他的代碼,其作用是在需要的時候方便調(diào)用這段(回調(diào)函數(shù))代碼。(作為參數(shù)傳遞到另外一個函數(shù)中,這個作為參數(shù)的函數(shù)就是回調(diào)函數(shù))
理解:函數(shù)可以作為一個參數(shù)傳遞到另外一個函數(shù)中。
<script> function add(num1, num2, callback) { var sum = num1 + num2; callback(sum); } function print(num) { console.log(num); } add(1, 2, print); //3 </script>
分析:add(1, 2, print);中,函數(shù)print作為一個參數(shù)傳入到add函數(shù)中,但并不是馬上起作用,而是var sum = num1 + num2;運行完之后需要打印輸出sum的時候才會調(diào)用這個函數(shù)。(這個作為參數(shù)傳遞到另外一個函數(shù)中,這個作為參數(shù)的函數(shù)就是回調(diào)函數(shù).
匿名回調(diào)函數(shù):
<script> function add(num1, num2, callback) { var sum = num1 + num2; callback(sum); } add(1, 2, function (sum) { console.log(sum); //=>3 }); </script>
2.回調(diào)函數(shù)有哪些特點?
1.不會立即執(zhí)行
回調(diào)函數(shù)作為參數(shù)傳遞給一個函數(shù)的時候,傳遞的只是函數(shù)的定義并不會立即執(zhí)行。和普通的函數(shù)一樣,回調(diào)函數(shù)在調(diào)用函數(shù)數(shù)中也要通過()
運算符調(diào)用才會執(zhí)行。
2.回調(diào)函數(shù)是一個閉包
回調(diào)函數(shù)是一個閉包,也就是說它能訪問到其外層定義的變量。
3.執(zhí)行前類型判斷
在執(zhí)行回調(diào)函數(shù)前最好確認其是一個函數(shù)。
<script> function add(num1, num2, callback) { var sum = num1 + num2; //判定callback接收到的數(shù)據(jù)是一個函數(shù) if (typeof callback === 'function') { //callback是一個函數(shù),才能當回調(diào)函數(shù)使用 callback(sum); } } </script>
3.回調(diào)函數(shù)中this的指向問題
注意在回調(diào)函數(shù)調(diào)用時this的執(zhí)行上下文并不是回調(diào)函數(shù)定義時的那個上下文,而是調(diào)用它的函數(shù)所在的上下文。
舉例:
<script> function createData(callback){ callback(); } var obj ={ data:100, tool:function(){ createData(function(n){ console.log(this,1111); //window 1111 }) } } obj.tool(); </script>
分析:this指向是 離它最近的或者嵌套級別的 function/方法的調(diào)用者,這里離它最近的function是
function(n),會回到上面的callback()中,這時候調(diào)用者就不是obj而是window。
解決回調(diào)函數(shù)this指向的方法1:箭頭函數(shù)
回調(diào)函數(shù)(若回調(diào)函數(shù)是普通函數(shù)時)當參數(shù)傳入另外的函數(shù)時,若不知道這個函數(shù)內(nèi)部怎么調(diào)用回調(diào)函數(shù),就會出現(xiàn)回調(diào)函數(shù)中的this指向不明確的問題(就比如上面例子中this指向的不是obj而是window)。所以 把箭頭函數(shù)當回調(diào)函數(shù),然后作為參數(shù)傳入另外的函數(shù)中就不會出現(xiàn)this指向不明的問題。
<script> function createData(callback){ callback(); } var obj ={ data:100, tool:function(){ createData((n)=>{ this.data = n; }) } } obj.tool(); console.log(obj.data); </script>
分析:回調(diào)函數(shù)用箭頭函數(shù)寫之后,this指向很明確,就是 離它最近的或者嵌套級別的 function/方法的調(diào)用者,所以這里是 obj 。
解決回調(diào)函數(shù)this指向的方法2:var self = this;
<script> function createData(callback){ callback(999); } var obj ={ data:100, tool:function(){ var self = this; //這里的this指向obj,然后當一個變量取用 createData(function(n){ self.data = n; }) } } obj.tool(); console.log(obj.data); </script>
4.為什么要用到回調(diào)函數(shù)?
有一個非常重要的原因 —— JavaScript 是事件驅(qū)動的語言。這意味著,JavaScript 不會因為要等待一個響應而停止當前運行,而是在監(jiān)聽其他事件時繼續(xù)執(zhí)行。來看一個基本的例子:
<script> function first() { console.log(1); } function second() { console.log(2); } first(); second(); </script>
分析:正如你所料,first
函數(shù)首先被執(zhí)行,隨后 second
被執(zhí)行 —— 控制臺輸出:1 2
但如果函數(shù) first
包含某種不能立即執(zhí)行的代碼會如何呢?例如我們必須發(fā)送請求然后等待響應的 API 請求?為了模擬這種狀況,我們將使用 setTimeout
,它是一個在一段時間之后調(diào)用函數(shù)的 JavaScript 函數(shù)。我們將函數(shù)延遲 500 毫秒來模擬一個 API 請求,新代碼長這樣:
<script> function first() { // 模擬代碼延遲 setTimeout(function () { //所以function(){console.log(1)}是回調(diào)函數(shù) console.log(1); }, 500); } function second() { console.log(2); } first(); second(); </script>
分析:這里 function(){console.log(1)}函數(shù)當作一個參數(shù)傳入setTimeout函數(shù)中,因為setTimeout是官方提供得一個函數(shù),里面有很多復雜的業(yè)務程序,所以函數(shù) function(){console.log(1)}傳入后,不一定馬上運行,要setTimeout里面要運行到function(){console.log(1)}時才會運行該函數(shù)參數(shù),那是不是整個程序就一直等setTimeout運行?不是的?。?!
整個程序運行結(jié)果為: 2 1 ,并不是原先的1 2 .即使我們首先調(diào)用了 first()
函數(shù),我們記錄的輸出結(jié)果卻在 second()
函數(shù)之后。
這不是 JavaScript 沒有按照我們想要的順序執(zhí)行函數(shù)的問題,而是 JavaScript 在繼續(xù)向下執(zhí)行 second()
之前沒有等待 first()
響應的問題。回調(diào)正是確保一段代碼執(zhí)行完畢之后再執(zhí)行另一段代碼的方式。
5.回調(diào)函數(shù)和異步操作的關(guān)系是什么?回調(diào)函數(shù)是異步么?
定義:回調(diào)函數(shù)被認為是一種高級函數(shù),一種被作為參數(shù)傳遞給另一個函數(shù)的高級函數(shù)?;卣{(diào)函數(shù)的本質(zhì)是一種模式(一種解決常見問題的模式),因此回調(diào)函數(shù)也被稱為回調(diào)模式。
簡而言之:一個函數(shù)在另一個函數(shù)中被調(diào)用。而且可以當參數(shù)傳給其他函數(shù)。
所以: 回調(diào)函數(shù)和異步操作的關(guān)系是沒有關(guān)系?。?!
那為什么很多的異步操作都有回填函數(shù)?。??
問:你所知道的異步操作,是回調(diào)的作用么??? 并不是。
回調(diào):更多的可以理解為一種業(yè)務邏輯把 異步編程:JS代碼的執(zhí)行順序
簡單理解:callback 顧名思義 打電話回來的意思
eg1:你點外賣,剛好你要吃的食物沒有了,于是你在店老板那里留下了你的電話,過了幾天店里有了,店員就打了你的電話,然后你接到電話后就跑到店里買了。在這個例子里,你的電話號碼就叫回調(diào)函數(shù),你把電話留給店員就叫登記回調(diào)函數(shù),店里后來有貨了叫做觸發(fā)了回調(diào)關(guān)聯(lián)的事件,店員給你打電話叫做調(diào)用回調(diào)函數(shù),你到店里去取貨叫做響應回調(diào)事件。
eg2:再比如,你發(fā)送一個axios 請求,請求成功之后,觸發(fā)成功的回調(diào)函數(shù),請求失敗觸發(fā)失敗的回調(diào)函數(shù)。這里面的回調(diào)函數(shù)更像是一個工具,后臺通過這個工具告訴你,你成功了抑或是失敗了。這里面的所有異步操作都和回調(diào)沒關(guān)系,真正的異步是then方法。
到此這篇關(guān)于JS中的 回調(diào)函數(shù)(callback)的文章就介紹到這了,更多相關(guān)js 回調(diào)函數(shù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用postMesssage()實現(xiàn)iframe跨域頁面間的信息傳遞
這篇文章主要介紹了使用postMesssage()實現(xiàn)iframe跨域頁面間的信息傳遞 的相關(guān)資料,需要的朋友可以參考下2016-03-03CodeMirror2 IE7/IE8 下面未知運行時錯誤的解決方法
最近用CodeMirror2作后臺的模板編輯器,在IE9、Firefox下面沒有問題。到了IE7、IE8下面,textarea里面的代碼就顯示不出來了。搜索了好多,終于找到原因2012-03-03微信小程序?qū)崿F(xiàn)自定義modal彈窗封裝的方法
這篇文章主要介紹了小程序自定義modal彈窗封裝實現(xiàn)方法,本文通過實例代碼相結(jié)合的形式給大家介紹的非常詳細,需要的朋友可以參考下2018-06-06JavaScript新手必看之var在for循環(huán)中的坑
var這個關(guān)鍵字在JS當中是相當常用的,但同時配合到for循環(huán)的話會出現(xiàn)不符合預期的運行結(jié)果,所以本文就來為大家講講如何避免這種情況的出現(xiàn)2023-05-05Javascript Request獲取請求參數(shù)如何實現(xiàn)
使用Javascript Request獲取參數(shù)的時候總是提示出錯,本文為此問題提供詳細的解決方案,需要了解的朋友可以參考下2012-11-11