編程中的函數(shù)是一個代碼塊,這個代碼塊中可以包含多條語句,然后通過該函數(shù)的標識符進行調(diào)用。
下面這個就是JS中的一個簡單函數(shù):

一、在JS中,如何創(chuàng)建一個函數(shù)?
-
方法一:構(gòu)造函數(shù)(該方法較少使用)
1.使用new和Function構(gòu)造一個函數(shù)
如下代碼:先聲明一個變量作為函數(shù)的標識符,然后使用new關(guān)鍵字后接Function進行構(gòu)造:
new關(guān)鍵字構(gòu)造一個空函數(shù)
2.構(gòu)造函數(shù)的參數(shù)
在上面例子中,我們還可以對fn函數(shù)內(nèi)部傳入?yún)?shù)和代碼塊,填寫在Function后面的括號內(nèi),如果傳入函數(shù)參數(shù),就要寫在第一位,函數(shù)的代碼塊部分寫在最后面,可以傳遞無數(shù)個參數(shù),也可以不傳遞參數(shù):
PS:這些參數(shù)都必須使用字符串的形式傳入,然后Function的F是大寫的
帶有參數(shù)的函數(shù)fn
沒有參數(shù)的函數(shù)fn -
方法二:函數(shù)表達式
1.介紹:函數(shù)表達式創(chuàng)建函數(shù)與new關(guān)鍵字的方式有點類似,但是不同的是,它是直接將函數(shù)體賦值給一個變量,該變量作為函數(shù)的標識符,然后可以通過該變量直接調(diào)用:
函數(shù)表達式創(chuàng)建函數(shù)
2.函數(shù)表達式參數(shù)的傳遞可以直接寫在小括號里面,多個參數(shù)時用逗號隔開:
函數(shù)表達式的參數(shù)
-
方法三、函數(shù)聲明(該方法最常用)
1.介紹:函數(shù)聲明是直接使用關(guān)鍵詞function后接標識符進行創(chuàng)建函數(shù),如下圖:
函數(shù)聲明創(chuàng)建函數(shù)
2.函數(shù)聲明創(chuàng)建函數(shù)的參數(shù)傳遞同函數(shù)表達式一樣,都是可以直接寫在小括號內(nèi)進行傳遞,可以多個,用逗號隔開; -
三種創(chuàng)建函數(shù)方式的不同點
主要不同是構(gòu)造函數(shù)和函數(shù)表達式:
構(gòu)造函數(shù)和函數(shù)表達式存在變量提升的問題,也就是說調(diào)用該函數(shù)必須在該函數(shù)已經(jīng)被創(chuàng)建后才能調(diào)用,而函數(shù)聲明不存在這個問題,無論在何處調(diào)用都可以,比如下圖:
函數(shù)表達式的調(diào)用必須在函數(shù)后面
調(diào)用成功
而函數(shù)聲明則沒有這個問題,它可以在任何地方被調(diào)用:
函數(shù)聲明
函數(shù)聲明
二、關(guān)于函數(shù)聲明的前置
大家都知道JS的執(zhí)行是由上至下的,而這對函數(shù)聲明和var變量是有重大影響的;
-
函數(shù)聲明與var變量一樣,會在JS加載到的時候自動放到所有代碼的最上面最先執(zhí)行,比如下面這個代碼,執(zhí)行的順序其實是這樣的:
看起來的執(zhí)行順序
真實的執(zhí)行順序 -
再來看看為什么函數(shù)表達式和構(gòu)造函數(shù)的調(diào)用要放到函數(shù)體的后面
原因是var變量會被置頂?shù)絁S的最上面,而此時如果函數(shù)還沒有被創(chuàng)建就調(diào)用了,自然就會出錯,比如下面這串代碼:
錯誤代碼
它的真是執(zhí)行順序是這樣的:
真實執(zhí)行順序
構(gòu)造函數(shù)同理。
三、函數(shù)的參數(shù)
-
給函數(shù)設(shè)置參數(shù),實際上就是在函數(shù)內(nèi)部聲明變量,而傳參相當于復制給這個函數(shù)內(nèi)的變量,比如下面這個函數(shù):
有參數(shù)的函數(shù)
當我執(zhí)行它時,實際上的步驟是這樣的:
函數(shù)內(nèi)部創(chuàng)建變量 關(guān)于函數(shù)的重載(同名函數(shù)的不同調(diào)用)
首先,函數(shù)是可以設(shè)置多個參數(shù)的,只需用逗號隔開,輸入時按照順序輸入即可;
-
在強類型編程語言中,因為申明變量的時候還必須聲明儲存的數(shù)據(jù)類型,所以在這些語言的函數(shù)只能夠,就可以根據(jù)輸入實參的數(shù)據(jù)類型和個數(shù)的不同來實現(xiàn)函數(shù)的重載功能;
例如在C語言中的重載功能:
C語言的函數(shù)重載功能 -
但是JS是一門弱類型的腳本語言,它對于變量的聲明只需要使用var即可,所以就不能根據(jù)實參的數(shù)據(jù)類型和個數(shù)來分別執(zhí)行有不同代碼段的同名函數(shù),如果創(chuàng)建了同名函數(shù),那么后創(chuàng)建的函數(shù)會覆蓋先創(chuàng)建的函數(shù),如下圖:
- JS函數(shù)重載功能的實現(xiàn)
1.JS雖然不能根據(jù)數(shù)據(jù)的類型來實現(xiàn)重載,但是可以使用條件判斷來實現(xiàn)重載
條件判斷實現(xiàn)JS函數(shù)重載
2.使用函數(shù)的參數(shù)屬性arguments來實現(xiàn)對函數(shù)參數(shù)個數(shù)的重載,例如實現(xiàn)計算不定參數(shù)個數(shù)的和:
arguments實現(xiàn)不定參數(shù)的和
四、函數(shù)的返回值(return)
return是需要函數(shù)返回一個結(jié)果時使用的關(guān)鍵字;
1.可以使函數(shù)得到的值用做他用,如下:

2.如果不寫return,函數(shù)會默認返回undefined,如下可以證明:

3.函數(shù)的返回值與console.log()的值不同,還是以上面那個例子做證明:

再執(zhí)行
var a = fn('a')時,輸出了一次a,而這個a并不是函數(shù)fn的值,它是console.log(a)執(zhí)行的結(jié)果,而函數(shù)返回的是a下面的那個undefined;
4.函數(shù)執(zhí)行過程中遇到return會立即結(jié)束函數(shù),后面的代碼不執(zhí)行,如下:

五、立即執(zhí)行函數(shù)
聲明函數(shù)和匿名函數(shù)
1.無論是構(gòu)造函數(shù),函數(shù)表達式還是函數(shù)聲明,它們都需要一個函數(shù)的名字,這是聲明函數(shù);
2.匿名函數(shù)是指一個函數(shù)沒有名字,并且被立刻調(diào)用,立即執(zhí)行函數(shù)就是匿名函數(shù),即使它的可以起名字的,但是這個函數(shù)名沒有任何意義;立即執(zhí)行函數(shù)的常用寫法
1.用小括號包裹整個函數(shù)體,然后在后面再添加一個小括號進行調(diào)用
(function(){})()
2.用小括號包含整個函數(shù)體,并且包含用以調(diào)用的小括號
(function(){}())
3.用+運算符鏈接函數(shù)體
+function(){}()-
根據(jù)立即執(zhí)行函數(shù)的寫法得到的一些結(jié)論:
- 立即執(zhí)行函數(shù)是運算符和函數(shù)的結(jié)合:
無論是小括號又或者是+號都是運算符,將它們與函數(shù)進行連接后,就是立即執(zhí)行函數(shù),按照這種說法,那么以下運算符也可以生效
1.-運算符:
2.=運算符:
3.!運算符:
4.,運算符:
PS:*、/、%不能使立即執(zhí)行函數(shù)得出結(jié)果并且會報錯; -
立即執(zhí)行函數(shù)其實是一個表達式,不會受到函數(shù)聲明前置的影響,以下代碼可以證明:
可見該函數(shù)是在a被賦值為100后才被創(chuàng)建并執(zhí)行的;
- 立即執(zhí)行函數(shù)是運算符和函數(shù)的結(jié)合:
立即執(zhí)行函數(shù)的作用
立即執(zhí)行函數(shù)的作用主要是防止變量的污染,在函數(shù)自身內(nèi)部創(chuàng)建一個局部作用域,所有在該函數(shù)內(nèi)部創(chuàng)建的變量都會在執(zhí)行后被銷毀,對外部變量沒有影響;
























