新手小白對(duì)回調(diào)函數(shù)的理解
只是寫(xiě)寫(xiě)自己的理解庆尘,借鑒了網(wǎng)上的一些文章剃诅,歡迎指正!
1.什么是函數(shù)
? ? ? ?要了解回調(diào)函數(shù)驶忌,就必須先了解函數(shù)矛辕。那么笑跛,什么是函數(shù)呢?
? ? ? ?如果要多處實(shí)現(xiàn)某個(gè)功能聊品,不用函數(shù)的話(huà)就要寫(xiě)很多次飞蹂,增加代碼量,浪費(fèi)時(shí)間翻屈;如果要修改這個(gè)功能陈哑,那就要多處修改,非常不方便伸眶。使用函數(shù)可以減少代碼量惊窖,方便后期修改。
? ? ? ?在JavaScript 中定義函數(shù)的方法有 3 種厘贼,即使用 function 語(yǔ)句爬坑、使用 Function() 構(gòu)造函數(shù)和定義函數(shù)直接量。
? ? ?(1)使用 function 語(yǔ)句聲明函數(shù)涂臣。具體用法如下:
? ? ? ? ? ? function onDeleteMail ( [args] ) {
? ? ? ? ? ? ? ? ? ? //statements
? ? ? ? ? ? }
? ? ? ?onDeleteMail 是函數(shù)名盾计,與變量名一樣必須是 JavaScript 合法的標(biāo)識(shí)符。在函數(shù)名之后是一個(gè)由一個(gè)小括號(hào)包含的參數(shù)列表赁遗,參數(shù)之間以逗號(hào)分隔署辉。參數(shù)是可選的,沒(méi)有數(shù)量限制岩四。
? ? ? ? 作為標(biāo)識(shí)符哭尝,參數(shù)僅在函數(shù)體內(nèi)被訪(fǎng)問(wèn),參數(shù)是函數(shù)作用域的私有成員剖煌。調(diào)用函數(shù)時(shí)材鹦,通過(guò)為函數(shù)傳遞值,然后使用參數(shù)獲取外部傳入的值耕姊,并在函數(shù)體內(nèi)干預(yù)函數(shù)的運(yùn)行桶唐。
? ? ? ? 在小括號(hào)之后是一個(gè)大括號(hào),大括號(hào)內(nèi)包含的語(yǔ)句就是函數(shù)體結(jié)構(gòu)的主要內(nèi)容茉兰,大括號(hào)是必不可少的尤泽,缺少大括號(hào),JavaScript 將會(huì)拋出語(yǔ)法錯(cuò)誤规脸。
? ? ? ?function 語(yǔ)句必須包含函數(shù)名坯约、小括號(hào)和大括號(hào),其他代碼都可省略莫鸭,因此最簡(jiǎn)單的函數(shù)體是一個(gè)空函數(shù)闹丐。
? ? ? ? ? ? ? ? function ?onDeleteMail( ) { }? //空函數(shù)
? ? ? ? 如果使用匿名函數(shù),則可以省略函數(shù)名被因。
? ? ? ? ? ? ? ? ?function ( ) { }? //匿名空函數(shù)
? ? ? ? var 語(yǔ)句和 function 語(yǔ)句都是聲明語(yǔ)句卿拴,它們聲明的變量和函數(shù)都在 JavaScript 預(yù)編譯時(shí)被解析衫仑,也被稱(chēng)為變量提升和函數(shù)提升。在預(yù)編譯期巍棱,JavaScript 引擎會(huì)為每個(gè) function 創(chuàng)建上下文惑畴,定義變量對(duì)象,同時(shí)把函數(shù)內(nèi)所有形參航徙、私有變量如贷、嵌套函數(shù)作為屬性注冊(cè)到變量對(duì)象上。
? ? ? (2)Function() 構(gòu)造函數(shù)// 此方法并不常用
? ? ? ? 使用 Function( ) 構(gòu)造函數(shù)可以快速生成函數(shù)到踏。具體用法如下:
? ? ? ? ?var? boy = new Function (p1 , p2 , ... , pn , body) ;
? ? ? ? Function( ) 的參數(shù)類(lèi)型都是字符串杠袱,p1~pn 表示所創(chuàng)建函數(shù)的參數(shù)名稱(chēng)列表,body 表示所創(chuàng)建函數(shù)的函數(shù)結(jié)構(gòu)體語(yǔ)句窝稿,在 body 語(yǔ)句之間以分號(hào)分隔楣富。
? ? ? ? ?使用 Function( ) 構(gòu)造函數(shù)可以不指定任何參數(shù),創(chuàng)建一個(gè)空函數(shù)結(jié)構(gòu)體伴榔。
? ? ? ? ? ? ?var f = new Function( ); //定義空函數(shù)
? ? ? ?使用 Function() 構(gòu)造函數(shù)可以動(dòng)態(tài)的創(chuàng)建函數(shù)纹蝴,它不會(huì)把用戶(hù)限制在 function 語(yǔ)句預(yù)聲明的函數(shù)體中。使用 Function() 構(gòu)造函數(shù)能夠把函數(shù)當(dāng)做表達(dá)式來(lái)使用踪少,而不是當(dāng)做一個(gè)結(jié)構(gòu)塘安,因此使用起來(lái)會(huì)更靈活。其缺點(diǎn)就是援奢,F(xiàn)unction() 構(gòu)造函數(shù)在執(zhí)行期被編譯兼犯,執(zhí)行效率非常低,一般不推薦使用集漾。
? ? (3)匿名函數(shù)(函數(shù)直接量)
? ? ? ?函數(shù)直接量也稱(chēng)為匿名函數(shù)切黔,即函數(shù)沒(méi)有函數(shù)名,僅包含 function 關(guān)鍵字具篇、參數(shù)和函數(shù)體纬霞。具體用法如下:
? ? ? ? ? ? ?function ( [args] ) {
? ? ? ? ? ? ? ? ? ? ? ? ?// statements
? ? ? ? ? ? ? }
? ? ? ? ?示例1:
? ? ? ? 下面代碼定義一個(gè)函數(shù)直接量。
? ? ? ? ? ? ? //函數(shù)直接量
? ? ? ? ? ? ? function ( a , b ){
? ? ? ? ? ? ? ? ? ?return a+b;
? ? ? ? ? ? ? ?}
? ? ? ? 在上面代碼中栽连,函數(shù)直接量與使用 function 語(yǔ)句定義函數(shù)結(jié)構(gòu)基本相同险领,它們的結(jié)構(gòu)都是固定的。但是函數(shù)直接量沒(méi)有指定函數(shù)名秒紧,而是直接利用關(guān)鍵字 function 來(lái)表示函數(shù)的結(jié)構(gòu),這種函數(shù)也被稱(chēng)為匿名函數(shù)挨下。
? ? ? ?示例2:
? ? ? ?匿名函數(shù)就是一個(gè)表達(dá)式熔恢,即函數(shù)表達(dá)式,而不是函數(shù)結(jié)構(gòu)的語(yǔ)句臭笆。下面把匿名函數(shù)作為一個(gè)值賦值給變量 f叙淌。
? ? ? ? ?//把函數(shù)作為一個(gè)值直接賦值給變量 f
? ? ? ? ? var? f = function ( a, b){
? ? ? ? ? ? ? return a+b;
? ? ? ? ? };
? ? ? ? 當(dāng)把函數(shù)結(jié)構(gòu)作為一個(gè)值賦值給變量之后秤掌,變量就可以作為函數(shù)被調(diào)用,此時(shí)變量就指向那個(gè)匿名函數(shù)鹰霍。
? ? ? ? console.log ( f ( 1,2 ) );? //返回值3
? ? ? ?示例3:
? ? ? ?匿名函數(shù)作為值闻鉴,可以參與更復(fù)雜的表達(dá)式運(yùn)算。針對(duì)上面示例可以使用以下代碼完成函數(shù)定義和調(diào)用一體化操作茂洒。
? ? ? ?//把函數(shù)作為一個(gè)操作數(shù)進(jìn)行調(diào)用
? ? ? ? ?console.log(?
? ? ? ? ? ? ? ? ( function(a,b) {
? ? ? ? ? ? ? ? ? ? ? ? ?return a+ b;
? ? ? ? ? ? ? ? })(1,2));? //返回?cái)?shù)值3
? ? ?(4)定義嵌套函數(shù)
? ? ? ?JavaScript 允許函數(shù)相互嵌套孟岛,因此可以定義復(fù)雜的嵌套結(jié)構(gòu)函數(shù)。
? ? ? ?示例1:
? ? ? ?使用 function 語(yǔ)句聲明兩個(gè)相互嵌套的函數(shù)體結(jié)構(gòu)督勺。
? ? ? ? ? ? function? f (x,y) {? //外層函數(shù)
? ? ? ? ? ? ? ? ? ? ?functione (a,b){? ?//內(nèi)層函數(shù)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? return? a*b ;
? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? return? x+y;
? ? ? ? ? ?}
? ? ? ? ?示例2:
? ? ? ? ? ? ? ?嵌套的函數(shù)只能在函數(shù)體內(nèi)可見(jiàn)渠羞,函數(shù)外不允許直接訪(fǎng)問(wèn)、調(diào)用智哀。
? ? ? ? ? ? ? ? function? f (x,y) {
? ? ? ? ? ? ? ? ? ? ? ?function? ?e (a,b) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?return? a*b;
? ? ? ? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? ? ? ? return? ?e (3, 6) + y;? ? //內(nèi)層函數(shù)參與表達(dá)式運(yùn)算有效
? ? ? ? ? ? ? ? ? ? ? console.log? (e (3,6) );? //無(wú)效的調(diào)用
? ? ? ? ? ? ? }
? ? ? ? ? ? ?console.log ( f (3,6) ) ;? ? //調(diào)用外層函數(shù)
2.什么是回調(diào)函數(shù)
? ? ? ?回調(diào)函數(shù)就是一個(gè)被作為參數(shù)傳遞給另一個(gè)函數(shù)次询,回調(diào)函數(shù)早另一個(gè)函數(shù)中被調(diào)用。眾所周知瓷叫,函數(shù)被大量使用的原因即為:一段代碼需要被多處調(diào)用屯吊,將此段代碼封裝至一個(gè)函數(shù)體內(nèi),可在多處調(diào)用摹菠,減少代碼量盒卸。而回調(diào)函數(shù)是為了解決多處調(diào)用時(shí),后續(xù)操作的不同辨嗽。比如說(shuō)世落,周五了老師給同學(xué)們布置作業(yè),老師可以選擇分別給每一個(gè)同學(xué)布置一遍作業(yè)糟需,也可以將同學(xué)們聚到一起屉佳,一次就把作業(yè)布置完成。這就像一個(gè)函數(shù)洲押,封裝一次武花,多次使用。但是老師把作業(yè)布置好以后杈帐。每個(gè)學(xué)生會(huì)用自己的方式完成体箕,可能有些學(xué)生周五全部寫(xiě)完,有些同學(xué)攢到周天才寫(xiě)作業(yè)挑童,這就是回調(diào)函數(shù)累铅。
? ? ? ?那么什么時(shí)候回調(diào)函數(shù)會(huì)進(jìn)行調(diào)用嗎?
? ? ? ?① 發(fā)生事件時(shí)站叼,例如娃兽,用戶(hù)單擊按鈕,或者用戶(hù)從下拉列表中選擇某些選項(xiàng)等等尽楔。
? ? ? ? 示例:DOM事件回調(diào)函數(shù)
? ? ? ? ? documet . getElementById ('btn') .onclick = function( ){
? ? ? ? ? ? ? ? ?alert? 'hello world' ;
? ? ? ? ? };
? ? ? ② 定時(shí)器回調(diào)函數(shù)
? ? ? ? ?setTimeout? ( function( ){
? ? ? ? ? ? ? ? console.log('兩秒過(guò)去了');
? ? ? ? ?} , 2000? );
? ??
??