前言
其實我一直很困惑關於js 中的callback,困惑的原因是,學習中這塊看的資料少,但是平時又經常見,偶爾復制一下前人代碼,功能實現了也就不再去追其原由,這么着,這個callback的概念就越來越混亂,因為你總感覺它是你Ajax請求后調用的那個函數,又感覺它是你某一個函數中的形參而已,而當你有一天看到一點關於Node.js的代碼后你會更加崩潰,因為你會發現很多的callback,但是這么着下去肯定是不行的,因為很多的東西如果只是知道概念和理論,沒有實踐出結果,沒有思考和感受,這些東西永遠不是你的,所以任何關於技術上用到的東西都應該去花時間鑽研一下,學習 付出時間 實踐都會搞明白的,還會沉淀很多思想,所以最近一直在瀏覽相關的文章和資料,自己在項目中也用到了一些去實踐,這樣一輪下來后,你會發現明亮了很多
一 .搞清楚異步和同步
異步async/同步sync
舉個小栗子
1.早上起來不論你是先刷牙還是先洗臉,都要等一個事情完畢后才能進行下一項,這就是一個同步的例子
2.然后刷牙的時候你也可以燒水喝 (不用等你刷完牙)這就是一個異步的例子
來段異步代碼示例


以上代碼會先執行函數a,而且不會等到a中的延遲函數執行完才執行函數b, 在延遲函數被觸發的過程中就執行了函數b,當js引擎的event 隊列空閑時才會去執行隊列里等待的setTimeout的回調函數,這就是一個異步的例子
題外話:
調用 setTimeout 函數會在一個時間段過去后在隊列中添加一個消息。這個時間段作為函數的第二個參數被傳入。如果隊列中沒有其它消息,消息會被馬上處理。但是,如果有其它消息,setTimeout 消息必須等待其它消息處理完。因此第二個參數僅僅表示最少的時間 而非確切的時間
所以即使,時間設置為0,也是會照樣先執行函數b
來段同步代碼示例

print函數會等change函數完成之后去執行,所以結構輸出為1,因為change函數修改了全局變量a的值,change執行之后才執行的print函數
二.回調函數到底是什么
A callback is a function that is passed as an argument to another function and is executed after its parent function has completed.
以上解釋是Google得出的解釋,非常清晰簡明,有時候我覺得英文理解要比翻譯成中文二次理解更清楚
來看幾個經典的回調函數代碼,我敢保證你一定用過他們




所以回調與同步、異步並沒有直接的聯系,回調只是一種實現方式,既可以有同步回調,也可以有異步回調,還可以有事件處理回調和延遲函數回調,這些在我們工作中有很多的使用場景
所以其實並不是我們不認識回調函數,而是我們都縈繞在了這個“callback“ 這個詞上,當你在一個函數中看到它是就會困惑,其實它只是一個形參名字而已
三.為什么寫回調函數
看了以上的簡單介紹之后,是不是對callback不再陌生和覺得神秘,所以盡情的去使用吧,
1.關於回調函數和js單線程以及js異步機制
我們都知道js是單線程的,這種設計模式給我們帶來了很多的方便之處,我們不需要考慮各個線程之間的通信,也不需要寫很多燒腦的代碼,也就是說js的引擎只能一件一件事的去完成和執行相關的操作,所以所有需要執行的事情都像排隊一樣,等待着被觸發和執行,可是如果這樣的話,如果在隊列中有一件事情需要花費很多的時間,那么后面的任務都將處於一種等待狀態,有時甚至會出現瀏覽器假死現象,例如其中有一件正在執行的一個任務是一個死循環,那么會導致后續其他的任務無法正常執行,所以js在同步機制的缺陷下設計出了異步模式
在異步執行的模式下,每一個異步的任務都有其自己一個或着多個回調函數,這樣當前在執行的異步任務執行完之后,不會馬上執行事件隊列中的下一項任務,而是執行它的回調函數,而下一項任務也不會等當前這個回調函數執行完,因為它也不能確定當前的回調合適執行完畢,只要引它被觸發就會執行,舉個例子,

上圖可以看到,我要購買一個東西,當我點進物品的詳情頁之后,圖片資源還未請求完畢,而此時我就可以點擊add to cart, 發起另一個請求,js任務列表中的添加購物車事件就會開始執行,它的執行也不會干擾到圖片資源的請求任務,這也是異步執行機制的妙處
2.js的單線程瀏覽器內核的多線程
說到js的單線程,順便再了解一下關於瀏覽器內核的多線程,關於瀏覽器工作原理此處不做講解,因為自己研究的不深入,等待研究學習研究透徹再分享

瀏覽器常駐三大線程: js引擎線程,GUI渲染線程,瀏覽器事件觸發線程
看到此圖你是不是會豁然開朗許多,因為瀏覽器是一個多線程的執行環境,在瀏覽器的內核中分配了多個線程,最主要的線程之一即是js引擎的線程,同時js事件隊列中的異步請求,交互事件觸發,定時器等事件都是由瀏覽器的事件觸發線程進行監聽的,瀏覽器的事件觸發線程被觸發后會把任務加入到js 引擎的任務隊列中,當js 引擎空閑時候就會開始執行該任務
完結
以上就是本篇文章的全部內容,由對回調函數的陌生到熟悉和使用,以及對同步/異步的概念,還有js的執行機制以及瀏覽器內核的多線程機制相信大家都有了一個簡單的知識脈絡,希望通過此文提到的內容,每個小伙伴去查閱更深入的資料,於此同時我也會不斷的去修繕,所以我們不能做一個知其然而不知其所以然的程序員,要有充分的好奇心去學習它,帶着學習讓我們受益的心態去做和研究自己感興趣的東西是一件非常快樂的事情,希望我可以把我的快樂帶給每一位看文章的小伙伴,也希望你多多給我提出意見,讓我們一起在學習的路上共同發現和成長,2107年歡迎你和我一起做一個不斷努力學習的知識分子
說明:文章中的圖片均處於本人截圖和繪制,文字均屬原創,轉載請注明出處
作者:Cayley碩兒
鏈接:https://www.jianshu.com/p/6bc353e5f7a3
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。