建設(shè)銀行簽名通在網(wǎng)站哪里下載免費(fèi)制作自己的網(wǎng)頁(yè)
📃個(gè)人主頁(yè):「小楊」的csdn博客
🔥系列專欄:【JavaScript速成之路】
🐳希望大家多多支持🥰一起進(jìn)步呀!
文章目錄
- 前言
- 1,函數(shù)基礎(chǔ)
- 1.1,函數(shù)概念
- 1.2,函數(shù)使用
- 1.3,函數(shù)參數(shù)
- 1.4,函數(shù)返回值
- 2,函數(shù)進(jìn)階
- 2.1,函數(shù)表達(dá)式
- 2.2,回調(diào)函數(shù)
- 2.3,遞歸函數(shù)
- 3,作用域
- 3.1,作用域分類
- 3.2,變量分類
- 3.3,作用域鏈
- 4,閉包函數(shù)
- 5,預(yù)解析
- 結(jié)語(yǔ)
前言
📜前言:小楊在上一篇帶著大家一起學(xué)習(xí)了JavaScript中的數(shù)組,想必大家對(duì)JavaScript的數(shù)組知識(shí)已經(jīng)有所了解了,那么今天我們將繼續(xù)帶著大家學(xué)習(xí)一下JavaScript中的函數(shù)的相關(guān)知識(shí),希望大家收獲多多!
1,函數(shù)基礎(chǔ)
1.1,函數(shù)概念
函數(shù)就是封裝了一段可以被重復(fù)執(zhí)行調(diào)用的代碼塊。
函數(shù)引入的目的就是為了解決代碼的重復(fù)問題,讓代碼重復(fù)使用。
1.2,函數(shù)使用
函數(shù)使用可分為兩步,即聲明函數(shù)和調(diào)用函數(shù)兩部分。
1,聲明函數(shù)語(yǔ)法:
function 函數(shù)名(參數(shù)列表){//函數(shù)體
}
知識(shí)點(diǎn):
- function是聲明函數(shù)的關(guān)鍵字,必須全部小寫。
- 函數(shù)是完成某一功能的代碼,故函數(shù)名一般為動(dòng)詞。
- 函數(shù)不能自己調(diào)用自己。
2,調(diào)用函數(shù)語(yǔ)法:
函數(shù)名();
知識(shí)點(diǎn):
- 調(diào)用函數(shù)的時(shí)候千萬不要忘記添加小括號(hào)。
- 聲明函數(shù)本身并不會(huì)執(zhí)行代碼,只有調(diào)用函數(shù)時(shí)才會(huì)執(zhí)行函數(shù)體代碼。
- 口訣:代碼不調(diào)用,自己不執(zhí)行。
3,函數(shù)封裝
函數(shù)具有封裝代碼的效果,也就是把一個(gè)或者多個(gè)功能通過函數(shù)的方式封裝起來,對(duì)外只提供一個(gè)簡(jiǎn)單的函數(shù)接口。
封裝思想類似于將計(jì)算機(jī)內(nèi)部的主板,CPU中央處理器,內(nèi)存等硬件全部安裝到機(jī)箱里,對(duì)外只提供一些像電源接口,顯示接口,USB接口這樣簡(jiǎn)單的接口給用戶使用。
1.3,函數(shù)參數(shù)
在函數(shù)內(nèi)部的代碼中,當(dāng)某些值不能確定時(shí),可以通過函數(shù)的參數(shù)從外部接收,一個(gè)函數(shù)可以通過傳入不同的參數(shù)來完成不同的操作。
1,參數(shù)分類
函數(shù)參數(shù)分為形參和實(shí)參兩種。
-
形參是指在聲明函數(shù)時(shí),函數(shù)名后面的小括號(hào)里添加的一些參數(shù)。
-
實(shí)參是指在調(diào)用函數(shù)時(shí),傳遞給函數(shù)的對(duì)應(yīng)形參的一些參數(shù)。
為了更加直觀的辨別形參和實(shí)參,示例如下:
function 函數(shù)名(形參1,形參2,形參3....){ //函數(shù)聲明的小括號(hào)里面的參數(shù)//函數(shù)體代碼
}
函數(shù)名(實(shí)參1,實(shí)參2,實(shí)參3....); //函數(shù)調(diào)用的小括號(hào)里面的參數(shù)
知識(shí)點(diǎn):
-
函數(shù)的形參是形式上的參數(shù),因?yàn)楫?dāng)函數(shù)聲明時(shí),這個(gè)函數(shù)還沒有被調(diào)用,這些形參具體傳入值是不確定的。
-
函數(shù)的實(shí)參則是實(shí)際上的參數(shù),因?yàn)樵诤瘮?shù)調(diào)用時(shí),這些形參的值就會(huì)被確定下來,傳遞給與之對(duì)應(yīng)的形參。
2,參數(shù)數(shù)量
JavaScript函數(shù)參數(shù)的使用比較靈活,允許函數(shù)的形參和實(shí)參個(gè)數(shù)不同。
- 實(shí)參的個(gè)數(shù)等于形參的個(gè)數(shù)時(shí),函數(shù)正常執(zhí)行。
- 實(shí)參的個(gè)數(shù)多于形參的個(gè)數(shù)時(shí),函數(shù)也可正常執(zhí)行,多余的實(shí)參因無形參接收會(huì)被忽略。
- 實(shí)參的個(gè)數(shù)少于形參的個(gè)數(shù)時(shí),函數(shù)也可正常執(zhí)行,多余的形參類似于一個(gè)已聲明但未賦值的變量,其值為undefined。
為了更好地理解上述語(yǔ)法,示例如下:
<script>function getNums(num1,num2){console.log(num1,num2);}getNums(1); //實(shí)參個(gè)數(shù)少于形參個(gè)數(shù)getNums(1,2); //實(shí)參個(gè)數(shù)等于形參個(gè)數(shù)getNums(1,2,3); //實(shí)參個(gè)數(shù)多于形參個(gè)數(shù)
</script>
示例結(jié)果:
3,arguments
當(dāng)我們不確定有多少個(gè)參數(shù)傳遞的時(shí)候,我們就可以使用arguments來獲取。
在JavaScript中,arguments這個(gè)是啥?arguments實(shí)際上是當(dāng)前函數(shù)的一個(gè)內(nèi)置函數(shù)。
所有函數(shù)都內(nèi)置了一個(gè)arguments對(duì)象,arguments對(duì)象中存儲(chǔ)了傳遞的所有參數(shù)。
arguments展示形式是一個(gè)偽數(shù)組,因此可以像數(shù)組一樣進(jìn)行遍歷。
那數(shù)組與偽數(shù)組有啥區(qū)別呢?偽數(shù)組具有以下特性:
- 具有數(shù)組的length屬性
- 按索引方式進(jìn)行存儲(chǔ)數(shù)據(jù)
- 不具有數(shù)組的push,pop等方法
為了更好地理解arguments的使用,示例如下:
<script>function fn(){ console.log(arguments); //arguments里存儲(chǔ)所有傳遞過來的參數(shù)console.log(arguments.length); //arguments具有數(shù)組的length屬性console.log(arguments[0]); //arguments按索引方式進(jìn)行存儲(chǔ)數(shù)據(jù)}fn(1,2,3,4);
</script>
示例結(jié)果:
1.4,函數(shù)返回值
當(dāng)函數(shù)完成了函數(shù)代碼塊的基本功能后,需要通過函數(shù)的返回值來將函數(shù)的處理結(jié)果返回。
函數(shù)返回值是通過return語(yǔ)句來實(shí)現(xiàn)的,語(yǔ)法格式:
function 函數(shù)名(){return 要返回的值;
}
函數(shù)返回值使用有以下兩種方式:
1,通過變量接收返回值
var result = 函數(shù)名();
console.log(result);
2,直接輸出函數(shù)返回值
console.log(函數(shù)名());
知識(shí)點(diǎn):若函數(shù)沒有使用return返回一個(gè)值,則函數(shù)調(diào)用后獲取的返回結(jié)果為undefined。
為了更好地理解函數(shù)返回值的語(yǔ)法,示例如下:
<script>function getResult(){return 121;}var result = getResult();console.log(result);console.log(getResult());
</script>
示例結(jié)果:
2,函數(shù)進(jìn)階
2.1,函數(shù)表達(dá)式
函數(shù)表達(dá)式是將聲明的函數(shù)賦值給一個(gè)變量,通過變量完成函數(shù)的調(diào)用和參數(shù)的傳遞。
為了更好理解函數(shù)表達(dá)式,示例如下:
<script>var sum = function(num1,num2){ //函數(shù)表達(dá)式return num1 + num2;}; console.log(sum(13,14)); //調(diào)用函數(shù)
</script>
示例結(jié)果:
知識(shí)點(diǎn):
- 函數(shù)表達(dá)式與函數(shù)聲明的定義方式幾乎相同,不同的是函數(shù)表達(dá)式的定義必須在函數(shù)調(diào)用之前,而函數(shù)聲明的方式則不限制聲明與調(diào)用順序。
2.2,回調(diào)函數(shù)
回調(diào)函數(shù)指的是一個(gè)函數(shù)A作為參數(shù)傳遞給一個(gè)函數(shù)B,然后在函數(shù)B的函數(shù)體內(nèi)調(diào)用函數(shù)A,此時(shí)函數(shù)A被稱為回調(diào)函數(shù)。
其中,匿名函數(shù)常用作函數(shù)的參數(shù)傳遞,從而實(shí)現(xiàn)回調(diào)函數(shù)。
為了更好理解何為回調(diào)函數(shù)及使用,示例如下:
<script>function fn1(num1,num2,fn){return fn(num1,num2);}console.log(fn1(45,55,function(a,b){return a + b;}));
</script>
示例結(jié)果:
知識(shí)點(diǎn):
- 在函數(shù)中設(shè)置了回調(diào)函數(shù)后,可以根據(jù)調(diào)用時(shí)傳遞的不同參數(shù)(相加的函數(shù),相乘的函數(shù)等),在函數(shù)體中特定的位置實(shí)現(xiàn)不同的功能,相當(dāng)于在函數(shù)體內(nèi)根據(jù)用戶的需求來完成了不同功能的定制。
2.3,遞歸函數(shù)
函數(shù)的遞歸指的是一個(gè)函數(shù)在其函數(shù)體內(nèi)調(diào)用自身的過程。需要特別注意的是 ,函數(shù)遞歸只可在特定的情況下使用。
為了更好地理解何為遞歸函數(shù)及使用,示例如下:
<script>
function fun(n){if(n == 1){return 1;}return n * fun(n - 1);
}
var ret = fun(5);
console.log(ret);
</script>
示例結(jié)果:
示例說明:上述代碼定義了一個(gè)遞歸函數(shù)fun()用于實(shí)現(xiàn)n的階乘計(jì)算,當(dāng)n不等于1時(shí),遞歸當(dāng)前變量n乘以fun(n-1),直到n等于1時(shí),返回1。
注意:遞歸調(diào)用雖然在遍歷維數(shù)不固定的多維數(shù)組時(shí)非常適合,但它占用的內(nèi)存和資源比較多,同時(shí)難以實(shí)現(xiàn)和維護(hù),因此在開發(fā)中需謹(jǐn)慎使用。
3,作用域
3.1,作用域分類
一般來說,一段代碼中所用到的變量名或函數(shù)名并不總是有效和可用的,而限定這個(gè)名字的可用性的代碼范圍就是這個(gè)名字的作用域。
作用域的目的就是為了有效減少命名沖突的情況。變量需要先聲明后使用,但不意味著聲明變量后就可以在任意位置使用該變量。
例如,在函數(shù)聲明一個(gè)age變量,在函數(shù)外進(jìn)行訪問,就會(huì)出現(xiàn)age變量未定義的錯(cuò)誤。
<script>function fun(){var age = 19;}console.log(age);
</script>
示例結(jié)果:
從上述代碼可以知道,變量需要在它的作用域范圍內(nèi)才可以被使用,這個(gè)作用域被稱為變量的作用域。
JavaScript根據(jù)作用域使用范圍的不同,將其劃分為全局作用域,函數(shù)作用域和塊級(jí)作用域(ES6提供的)。
- 全局作用域是整個(gè)script標(biāo)簽 或者 一個(gè)單獨(dú)的JavaScript文件。
- 局部作用域也稱函數(shù)作用域,在函數(shù)內(nèi)部就是函數(shù)作用域,這個(gè)代碼名字只能在函數(shù)內(nèi)部起效果和作用。
為了更好理解上述語(yǔ)法,示例如下:
<script>//全局作用域var num = 20; //全局變量function fun(){//局部作用域var num = 10; //局部變量console.log(num); //輸出局部變量值:10}fun();console.log(num); //輸出全局變量值:20
</script>
3.2,變量分類
在JavaScript中,對(duì)不同的作用域內(nèi)聲明的變量進(jìn)行劃分,可劃分為全局變量,局部變量,塊級(jí)變量三類。
- 全局變量:不在任何函數(shù)內(nèi)聲明的變量(顯式定義)或在函數(shù)內(nèi)省略var聲明的變量隱式定義)都稱為全局變量,它在同一個(gè)頁(yè)面文件中的所有腳本內(nèi)都可以使用。
- 局部變量:在函數(shù)體內(nèi)利用var關(guān)鍵字定義的變量稱為局部變量,它僅在該函數(shù)體內(nèi)有效。
- 塊級(jí)變量:ES6提供的let關(guān)鍵字聲明的變量稱為塊級(jí)變量,僅在“0”中間有效,如if、for或while語(yǔ)句等。
知識(shí)點(diǎn):
- 當(dāng)全局變量名和局部變量名相同時(shí),兩者的使用互不影響。
- 局部變量只能在函數(shù)內(nèi)部使用,函數(shù)的形參也屬于局部變量。
- 函數(shù)中的變量如果省略var關(guān)鍵字,它會(huì)自動(dòng)向上級(jí)作用域查找變量,一直找到全局作用域?yàn)橹埂?/li>
<script>function fn(){num = 10;}fn();console.log(num);
</script>
-
在全局作用域下,添加或者省略var關(guān)鍵字都可以聲明全局變量。而在函數(shù)中,添加var關(guān)鍵字聲明的變量是局部變量,省略var關(guān)鍵字時(shí),如果變量在當(dāng)前作用域不存在,會(huì)自動(dòng)向上級(jí)作用域查找變量。
-
從執(zhí)行效率來說,全局變量在瀏覽器關(guān)閉頁(yè)面的時(shí)候才會(huì)銷毀,比較占用內(nèi)存資源;而局部變量在函數(shù)執(zhí)行完成后就會(huì)被銷毀,比較節(jié)約內(nèi)存資源。
3.3,作用域鏈
當(dāng)在一個(gè)函數(shù)內(nèi)部聲明另外一個(gè)函數(shù)時(shí),就會(huì)出現(xiàn)函數(shù)嵌套的效果。當(dāng)函數(shù)嵌套時(shí),內(nèi)層函數(shù)只能在外部函數(shù)作用域內(nèi)執(zhí)行,在內(nèi)層函數(shù)執(zhí)行過程中,若需要引入某個(gè)變量,首先會(huì)在當(dāng)前作用域中尋找,若未找到,則繼續(xù)向上一層級(jí)的作用域中尋找,直到全局作用域。
簡(jiǎn)而言之,作用域鏈?zhǔn)侵竷?nèi)部函數(shù)訪問外部函數(shù)的變量,采取的是鏈?zhǔn)讲檎业姆绞絹頉Q定那個(gè)值。
為了更好理解上述作用域鏈的語(yǔ)法,示例如下:
<script>var num = 10;function fn(){ //外部函數(shù)var num = 20;function fun(){ //內(nèi)部函數(shù)console.log(num); //輸出num值:20 } //口訣:就近原則fun();}fn();
</script>
示例結(jié)果:
4,閉包函數(shù)
在JavaScript中,內(nèi)嵌函數(shù)可以訪問定義在外層函數(shù)中的所有的變量和函數(shù),并包括其外層函數(shù)能訪問的所有變量和函數(shù)。
但是在函數(shù)外部則不能訪問函數(shù)的內(nèi)部變量和嵌套函數(shù),此時(shí)可通過使用閉包來實(shí)現(xiàn)。
**那閉包是啥東東呢?**閉包指的就是有權(quán)訪問另一函數(shù)作用域內(nèi)變量(局部變量)的函數(shù)。
那閉包有啥用呢? 閉包的用途可歸納為以下兩種:
- 可以在函數(shù)外部讀取函數(shù)內(nèi)部的變量。
- 可以讓變量的值始終在內(nèi)存中。
知識(shí)點(diǎn)1:由于閉包會(huì)使得函數(shù)中的變量一直被保存在內(nèi)存中,內(nèi)存消耗很大,所以濫用閉包可能會(huì)降低程序的處理速度,造成內(nèi)存消耗等問題
知識(shí)點(diǎn)2:常見的閉包創(chuàng)建的方式就是在一個(gè)函數(shù)內(nèi)部創(chuàng)建另外一個(gè)函數(shù),通過另外一個(gè)函數(shù)訪問這個(gè)函數(shù)的局部變量。
為了更好地理解該知識(shí)點(diǎn),示例如下:
<script>function fun(){var num = 0;var a = function(){return ++num;};return a;}//保存fun返回的函數(shù),此時(shí)ret就是一個(gè)閉包var ret = fun(); //訪問測(cè)試console.log(ret());console.log(ret());console.log(ret());console.log(ret());console.log(ret());
</script>
示例結(jié)果:
5,預(yù)解析
JavaScript代碼由瀏覽器中的JavaScript解析器來執(zhí)行的,JavaScript解析器在運(yùn)行JavaScript代碼時(shí)會(huì)進(jìn)行預(yù)解析。
**那該如何理解預(yù)解析呢?**預(yù)解析就是提前將代碼中的var變量聲明和function函數(shù)聲明進(jìn)行解析,然后再去執(zhí)行其它的代碼。
JavaScript引擎運(yùn)行JavaScript分為兩步:預(yù)解析和代碼執(zhí)行。
預(yù)解析分為變量預(yù)解析(變量提升)和函數(shù)預(yù)解析(函數(shù)提升)兩類。
- 變量提升就是將所有的變量聲明提升到當(dāng)前作用域的最前面,但不提升賦值操作。
- 函數(shù)提升就是將所有的函數(shù)聲明提升到當(dāng)前作用域的最前面,但不調(diào)用函數(shù)。
為了更好理解預(yù)解析的使用,示例如下:
預(yù)解析示例1:
<script>function fn(){var num2 = 456;console.log(num1);console.log(num2);var num1 = 123;}fn();
</script>
上述代碼經(jīng)過預(yù)解析的處理后:
<script>function fn(){var num2;var num1;num2 = 456;console.log(num1);console.log(num2);num1 = 123;}fn();
</script>
預(yù)解析示例1結(jié)果:
預(yù)解析示例2:
<script>fn1();console.log(c);console.log(b);console.log(a);function fn1(){var a = b = c = 9;console.log(a);console.log(b);console.log(c);}
</script>
上述代碼經(jīng)過預(yù)解析的處理后:
<script>function fn1(){var a;a = 9;b = 9;c = 9; //b和c為全局變量,a為局部變量console.log(a);console.log(b);console.log(c);}fn1();console.log(c);console.log(b);console.log(a);</script>
預(yù)解析示例2結(jié)果:
結(jié)語(yǔ)
這就是本期博客的全部?jī)?nèi)容啦,想必大家已經(jīng)對(duì)JavaScript中函數(shù)的相關(guān)內(nèi)容有了全新地認(rèn)識(shí)和理解吧,如果有什么其他的問題無法自己解決,可以在評(píng)論區(qū)留言哦!
最后,如果你覺得這篇文章寫的還不錯(cuò)的話或者有所收獲的話,麻煩小伙伴們動(dòng)動(dòng)你們的小手,給個(gè)三連唄(點(diǎn)贊👍,評(píng)論?,收藏📖),多多支持一下!各位的支持是我最大的動(dòng)力,后期不斷更新優(yōu)質(zhì)的內(nèi)容來幫助大家,一起進(jìn)步。那我們下期見!