JavaScript-函數(shù)

概念

函數(shù)(function)樟蠕,也叫作功能贮聂、方法,函數(shù)可以將一段代碼一起封裝起來寨辩,被封裝起來的函數(shù)具備某一項特殊的功能吓懈,內(nèi)部封裝的一段代碼作為一個完整的結(jié)構(gòu)體,要執(zhí)行就都執(zhí)行靡狞,要不執(zhí)行就都不執(zhí)行耻警。函數(shù)的作用就是封裝一段代碼,將來可以重復(fù)使用甸怕。

聲明

函數(shù)聲明又叫函數(shù)定義甘穿,函數(shù)必須先定義然后才能使用。如果沒有定義函數(shù)直接使用梢杭,會出現(xiàn)一個引用錯誤扒磁。函數(shù)聲明語法:

    function 函數(shù)名(參數(shù)){
        封裝的結(jié)構(gòu)體;
    }

特點(diǎn):函數(shù)聲明的時候式曲,函數(shù)體并不會執(zhí)行妨托,只有當(dāng)函數(shù)被調(diào)用的時候才會執(zhí)行。

調(diào)用

調(diào)用方法:函數(shù)名();
函數(shù)調(diào)用也叫作函數(shù)執(zhí)行吝羞,調(diào)用時會將函數(shù)內(nèi)部封裝的所有的結(jié)構(gòu)體的代碼立即執(zhí)行兰伤。
函數(shù)內(nèi)部語句執(zhí)行的位置,與函數(shù)定義的位置無關(guān)钧排,與函數(shù)調(diào)用位置有關(guān)敦腔。
函數(shù)可以一次定義,多次執(zhí)行恨溜。

參數(shù)

函數(shù)預(yù)留了一個接口符衔,專門用于讓用戶自定義內(nèi)容,使函數(shù)發(fā)生一些執(zhí)行效果變化糟袁。

  • 接口:就是函數(shù)的參數(shù)判族,函數(shù)參數(shù)的本質(zhì)就是變量,可以接收任意類型的數(shù)據(jù)项戴,導(dǎo)致函數(shù)執(zhí)行結(jié)果根據(jù)參數(shù)不同形帮,結(jié)果也不同。

一個函數(shù)可以設(shè)置 0 個或者多個參數(shù)周叮,參數(shù)之間用逗號分隔辩撑。

函數(shù)的參數(shù)根據(jù)書寫位置不同,名稱也不同:

  • 形式參數(shù):定義的 () 內(nèi)部的參數(shù)仿耽,叫做形式參數(shù)合冀,本質(zhì)是變量,可以接收實(shí)際參數(shù)傳遞過來的數(shù)據(jù)项贺。簡稱形參君躺。
  • 實(shí)際參數(shù):調(diào)用的 () 內(nèi)部的參數(shù)峭判,叫做實(shí)際參數(shù),本質(zhì)就是傳遞的各種類型的數(shù)據(jù)晰洒,傳遞給每個形參,簡稱實(shí)參啥箭。
    函數(shù)執(zhí)行過程谍珊,伴隨著傳參的過程:

    函數(shù)參數(shù)的優(yōu)點(diǎn):
  • 不論使用自己封裝的函數(shù),還是其他人封裝的函數(shù)急侥,只需要知道傳遞什么參數(shù)砌滞,執(zhí)行什么功能,沒必要知道內(nèi)部的結(jié)構(gòu)什么坏怪。
  • 一般自己封裝的函數(shù)或者其他人封裝的函數(shù)需要有一個 API 接口說明贝润,告訴用戶參數(shù)需要傳遞什么類型的數(shù)據(jù),實(shí)現(xiàn)什么功能铝宵。

返回值

函數(shù)能夠通過參數(shù)接收數(shù)據(jù)打掘,也能夠?qū)⒑瘮?shù)執(zhí)行結(jié)果返回一個值∨羟铮可以利用函數(shù)內(nèi)部的一個 return 的關(guān)鍵字設(shè)置函數(shù)的返回值尊蚁。

  • 作用 ①:函數(shù)內(nèi)部如果結(jié)構(gòu)體執(zhí)行到一個 return 的關(guān)鍵字,會立即停止后面代碼的執(zhí)行侣夷。
  • 作用 ②:可以在 return 關(guān)鍵字后面添加空格横朋,空格后面任意定義一個數(shù)據(jù)字面量或者表達(dá)式,函數(shù)在執(zhí)行完自身功能之后百拓,整體會被 return 矮化成一個表達(dá)式琴锭,表達(dá)式必須求出一個值繼續(xù)可以參與程序,表達(dá)式的值就是 return 后面的數(shù)據(jù)衙传。

函數(shù)如果有返回值决帖,執(zhí)行結(jié)果可以當(dāng)成普通數(shù)據(jù)參與程序,也可以作為一個普通數(shù)據(jù)賦值給一個變量蓖捶,甚至賦值給其他函數(shù)的實(shí)際參數(shù)古瓤。

注意:如果函數(shù)沒有設(shè)置 return 語句 ,那么函數(shù)有默認(rèn)的返回值 undefined腺阳;如果函數(shù)使用 return 語句落君,但是 return 后面沒有任何值,那么函數(shù)的返回值也是 undefined亭引。

表達(dá)式

函數(shù)表達(dá)式是函數(shù)定義的另外一種方式绎速。定義方法就是將函數(shù)的定義、匿名函數(shù)賦值給一個變量焙蚓。函數(shù)定義賦值給一個變量纹冤,相當(dāng)于將函數(shù)整體矮化成了一個表達(dá)式洒宝。匿名函數(shù)的意思是函數(shù)沒有函數(shù)名。調(diào)用函數(shù)表達(dá)式萌京,方法是給變量名加()執(zhí)行雁歌,不能使用函數(shù)名加()執(zhí)行。


數(shù)據(jù)類型

函數(shù)是一種單獨(dú)的數(shù)據(jù)類型 Function知残。由于函數(shù)是一種數(shù)據(jù)類型靠瞎,可以參與其他程序。例如求妹,可以把函數(shù)作為另一個函數(shù)的參數(shù)乏盐,在另一個函數(shù)中調(diào)用,或者制恍,可以把函數(shù)可以作為返回值從函數(shù)內(nèi)部返回父能。

arguments對象

JavaScript 中,arguments 對象是比較特別的一個對象净神,實(shí)際上是當(dāng)前函數(shù)的一個內(nèi)置屬性何吝。也就是說所有函數(shù)都內(nèi)置了一個 arguments 對象,arguments 對象中存儲了傳遞的所有的實(shí)參鹃唯。arguments 是一個偽數(shù)組岔霸,因此及可以進(jìn)行遍歷。
函數(shù)的實(shí)參個數(shù)和形參個數(shù)可以不一致俯渤,所有的實(shí)參都會存儲在函數(shù)內(nèi)部的 arguments 類數(shù)組對象中呆细。

function fun() {
  console.log(arguments);
}

遞歸

函數(shù)內(nèi)部可以通過函數(shù)名調(diào)用函數(shù)自身的方式,就是函數(shù)遞歸現(xiàn)象八匠。遞歸的次數(shù)太多容易出現(xiàn)錯誤:超出計算機(jī)的計算最大能力絮爷。更多時候,使用遞歸去解決一些數(shù)學(xué)中的現(xiàn)象梨树。例如可以輸出斐波那契數(shù)列的某一項的值坑夯。

// 菲波那切數(shù)列
// 參數(shù):正整數(shù)
// 返回值:對應(yīng)的整數(shù)位置的菲波那切數(shù)列的值
function fibo(a) {
  if (a === 1 || a === 2) {
    return 1;
  } else {
    return fibo(a - 1) + fibo(a - 2);
  }
}

作用域

作用域指變量可以起作用的范圍。如果變量定義在一個函數(shù)內(nèi)部抡四,只能在函數(shù)內(nèi)部被訪問到柜蜈,在函數(shù)外部不能使用這個變量,函數(shù)就是變量定義的作用域指巡。任何一對花括號 {} 中的結(jié)構(gòu)體都屬于一個塊淑履,在這之中定義的所有變量在代碼塊外都是不可見的,我們稱之為塊級作用域藻雪。在es6之前沒有塊級作用域的的概念,只有函數(shù)作用域秘噪。

全局變量和局部變量

  • 局部變量:定義在函數(shù)內(nèi)部的變量,只能在函數(shù)作用域內(nèi)部被訪問到勉耀,在外面沒有定義的指煎。
  • 全局變量:從廣義上來說蹋偏,也是一種局部變量,定義在全局的變量至壤,作用域范圍是全局威始,在整個 js 程序任意位置都能夠被訪問到。

變量退出作用域之后會銷毀像街,全局變量關(guān)閉網(wǎng)頁或瀏覽器才會銷毀黎棠。

函數(shù)的參數(shù)本質(zhì)是一個變量,也有自己的作用域宅广,函數(shù)的參數(shù)也是屬于函數(shù)自己內(nèi)部的局部變量葫掉,只能在函數(shù)內(nèi)部被使用些举,在函數(shù)外面沒有定義跟狱。

函數(shù)也有自己的作用域,定義在哪個作用域內(nèi)部户魏,只能在這個作用域范圍內(nèi)被訪問驶臊,出了作用域不能被訪問的。函數(shù)定義在另一個函數(shù)內(nèi)部叼丑,如果外部函數(shù)沒有執(zhí)行時关翎,相當(dāng)于內(nèi)部代碼沒寫。

作用域鏈

只有函數(shù)可以制造作用域結(jié)構(gòu)鸠信, 那么只要是代碼纵寝,就至少有一個作用域, 即全局作用域。凡是代碼中有函數(shù)星立,那么這個函數(shù)就構(gòu)成另一個作用域爽茴。如果函數(shù)中還有函數(shù),那么在這個作用域中就又可以誕生一個作用域绰垂。
將這樣的所有的作用域列出來室奏,可以有一個結(jié)構(gòu): 函數(shù)內(nèi)指向函數(shù)外的鏈?zhǔn)浇Y(jié)構(gòu)。就稱作作用域鏈劲装。

function f1() {
    function f2() {
    }
}
var num = 456;
function f3() {
    function f4() {    
    }
}
function f1() {
    var num = 123;
    function f2() {
        console.log(num); 
    }
    f2();
}
var num = 456;
f1();

遮蔽效應(yīng)

程序在遇到一個變量時胧沫,使用時作用域查找順序,不同層次的函數(shù)內(nèi)都有可能定義相同名字的變量占业,一個變量在使用時绒怨,會優(yōu)先從自己所在層作用域查找變量,如果當(dāng)前層沒有變量定義會按照順序從本層往外依次查找谦疾,直到找到第一個變量定義窖逗。整個過程中會發(fā)生內(nèi)層變量遮蔽外層變量的效果,叫做“遮蔽效應(yīng)”餐蔬。

不寫 var 關(guān)鍵字的影響:在函數(shù)內(nèi)部想要定義新的變量碎紊,如果不加關(guān)鍵字 var佑附,相當(dāng)于定義的全局變量。如果全局也有相同的標(biāo)識符仗考,會被函數(shù)內(nèi)部的變量影響音同,局部變量污染全局變量。所以每次定義變量時都必須寫 var 關(guān)鍵字秃嗜,否則就會定義在全局权均,可能污染全局。


預(yù)解析與聲明提升

預(yù)解析

JavaScript 代碼的執(zhí)行是由瀏覽器中的 JavaScript 解析器來執(zhí)行的锅锨。JavaScript 解析器執(zhí)行 JavaScript 代碼的時候叽赊,分為兩個過程:預(yù)解析過程和代碼執(zhí)行過程。
預(yù)解析過程:

  1. 把變量的聲明提升到當(dāng)前作用域的最前面必搞,只會提升聲明必指,不會提升賦值。
  2. 把函數(shù)的聲明提升到當(dāng)前作用域的最前面恕洲,只會提升聲明塔橡,不會提升調(diào)用。
  3. 先提升 var霜第,再提升 function葛家。

JavaScript 的執(zhí)行過程:在預(yù)解析之后,根據(jù)新的代碼順序泌类,從上往下按照既定規(guī)律執(zhí)行 js 代碼癞谒。

變量聲明提升

在預(yù)解析過程中,所有定義的變量刃榨,都會將聲明的過程提升到所在的作用域最上面弹砚,在將來的代碼執(zhí)行過程中,按照先后順序會先執(zhí)行被提升的聲明變量過程喇澡。
提升過程中迅栅,只提升聲明過程,不提升變量賦值晴玖,相當(dāng)于變量定義未賦值读存,變量內(nèi)存儲 undefined 值。
因此呕屎,在 js 中會出現(xiàn)一種現(xiàn)象让簿,在前面調(diào)用后定義的變量,不會報錯秀睛,只會使用 undefined 值尔当。

函數(shù)聲明提升

在預(yù)解析過程中,所有定義的函數(shù),都會將聲明的過程提升到所在的作用域最上面椭迎,在將來的代碼執(zhí)行過程中锐帜,按照先后順序會先執(zhí)行被提升的函數(shù)聲明過程。
在預(yù)解析之后的代碼執(zhí)行過程中畜号,函數(shù)定義過程已經(jīng)在最開始就會執(zhí)行缴阎,一旦函數(shù)定義成功,后續(xù)就可以直接調(diào)用函數(shù)简软。
因此蛮拔,在 js 中會出現(xiàn)一種現(xiàn)象,在前面調(diào)用后定義的函數(shù)痹升,不會報錯建炫,而且能正常執(zhí)行函數(shù)內(nèi)部的代碼。

提升順序

預(yù)解析過程中疼蛾,先提升 var 變量聲明肛跌,再提升 function 函數(shù)聲明。
假設(shè)出現(xiàn)變量名和函數(shù)名相同据过,那么后提升的函數(shù)名標(biāo)識符會覆蓋先提升的變量名惋砂,那么在后續(xù)代碼中出現(xiàn)調(diào)用標(biāo)識符時妒挎,內(nèi)部是函數(shù)的定義過程绳锅,而不是 undefined。
如果調(diào)用標(biāo)識符的過程在源代碼函數(shù)和變量定義后面酝掩,相當(dāng)于函數(shù)名覆蓋了一次變量名鳞芙,結(jié)果在執(zhí)行到變量賦值時,又被新值覆蓋了函數(shù)的值期虾,那么在后面再次調(diào)用標(biāo)識符原朝,用的就是變量存的新值。
建議:不要書寫相同的標(biāo)識符給變量名或函數(shù)名镶苞,避免出現(xiàn)覆蓋喳坠。

函數(shù)表達(dá)式的提升

在預(yù)解析過程中,函數(shù)表達(dá)式進(jìn)行的是變量聲明提升茂蚓,而不是函數(shù)聲明提升壕鹉。提升后變量內(nèi)部存的是一個 undefined。在前面進(jìn)行函數(shù)方法調(diào)用聋涨,數(shù)據(jù)類型會提示錯誤晾浴。
建議:定義函數(shù)時,最好使用 function 關(guān)鍵字定義方式牍白,這樣函數(shù)聲明提升可以永遠(yuǎn)生效脊凰。
函數(shù)聲明提升可以用于調(diào)整代碼的順序,將大段的定義過程放到代碼最后茂腥,但是不影響代碼執(zhí)行效果狸涌。


IIFE 自調(diào)用函數(shù)

IIFE:immediately-invoked function expression切省,叫做即時調(diào)用的函數(shù)表達(dá)式,也叫做自調(diào)用函數(shù)帕胆,表示函數(shù)在定義時就立即調(diào)用数尿。
函數(shù)調(diào)用方式:函數(shù)名或函數(shù)表達(dá)式的變量名后面加 () 運(yùn)算符。
函數(shù)名定義的形式不能實(shí)現(xiàn)立即執(zhí)行自調(diào)用惶楼,函數(shù)使用函數(shù)表達(dá)式形式可以實(shí)現(xiàn)立即執(zhí)行右蹦,原因是因為函數(shù)表達(dá)式定義過程中,將一個函數(shù)矮化成了一個表達(dá)式歼捐,后面加()運(yùn)算符就可以立即執(zhí)行何陆。
如果想實(shí)現(xiàn) IIFE,可以想辦法將函數(shù)矮化成表達(dá)式豹储。
函數(shù)矮化成表達(dá)式的方法贷盲,可以讓函數(shù)參與一些運(yùn)算,也就是說給函數(shù)前面加一些運(yùn)算符剥扣。

  • 數(shù)學(xué)運(yùn)算符:+ - ()
  • 邏輯運(yùn)算符:巩剖!非運(yùn)算

IIFE 結(jié)構(gòu)可以關(guān)住函數(shù)的作用域,在結(jié)構(gòu)外面是不能調(diào)用函數(shù)的钠怯。
IIFE 最常用的是 () 運(yùn)算符佳魔,而且函數(shù)可以不寫函數(shù)名,使用匿名函數(shù)晦炊。


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
禁止轉(zhuǎn)載鞠鲜,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者。
  • 序言:七十年代末断国,一起剝皮案震驚了整個濱河市贤姆,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌稳衬,老刑警劉巖霞捡,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異薄疚,居然都是意外死亡碧信,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進(jìn)店門输涕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來音婶,“玉大人,你說我怎么就攤上這事莱坎∫率剑” “怎么了?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長碴卧。 經(jīng)常有香客問我弱卡,道長,這世上最難降的妖魔是什么住册? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任婶博,我火速辦了婚禮,結(jié)果婚禮上荧飞,老公的妹妹穿的比我還像新娘凡人。我一直安慰自己,他們只是感情好叹阔,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布挠轴。 她就那樣靜靜地躺著,像睡著了一般耳幢。 火紅的嫁衣襯著肌膚如雪岸晦。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天睛藻,我揣著相機(jī)與錄音启上,去河邊找鬼。 笑死店印,一個胖子當(dāng)著我的面吹牛冈在,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播吱窝,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼讥邻,長吁一口氣:“原來是場噩夢啊……” “哼迫靖!你這毒婦竟也來了院峡?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤系宜,失蹤者是張志新(化名)和其女友劉穎照激,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體盹牧,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡俩垃,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了汰寓。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片口柳。...
    茶點(diǎn)故事閱讀 40,133評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖有滑,靈堂內(nèi)的尸體忽然破棺而出跃闹,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布望艺,位于F島的核電站苛秕,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏找默。R本人自食惡果不足惜艇劫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望惩激。 院中可真熱鬧店煞,春花似錦、人聲如沸风钻。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽魄咕。三九已至衩椒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間哮兰,已是汗流浹背毛萌。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留喝滞,地道東北人阁将。 一個月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像右遭,于是被迫代替她去往敵國和親做盅。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,077評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 一窘哈、函數(shù)的概念 函數(shù)是一段可以反復(fù)調(diào)用的代碼塊吹榴。 作用:在程序設(shè)計中,常將一些常用的功能模塊編寫成函數(shù)滚婉,以減少重復(fù)...
    MJ的小世界閱讀 149評論 0 1
  • 函數(shù) 理解參數(shù) JavaScript函數(shù)不介意傳遞多少個參數(shù)图筹,也不介意傳遞參數(shù)的數(shù)據(jù)類型。也就是說函數(shù)定義接受多少...
    TaoGeNet閱讀 216評論 0 2
  • 每天一句:想說會有多少人問自己一下幾個問題“你這輩子到底要什么,要做怎么樣的人骇窍?你現(xiàn)在能夠做什么瓜晤?你正在做什么?你...
    EndEvent閱讀 282評論 0 0
  • 1. JS函數(shù)的概念 2. 函數(shù)的作用 3. 使用函數(shù)的好處 4.函數(shù)的分類 函數(shù)可以分為: 系統(tǒng)函數(shù) 內(nèi)置...
    阿里P9王者閱讀 352評論 0 0
  • 立即執(zhí)行函數(shù) 變量聲明提前 使用var關(guān)鍵字聲明的變量腹纳,會在所有的代碼執(zhí)行之前聲明但聲明變量時不適用var關(guān)鍵字痢掠,...
    zhangxiaokun閱讀 274評論 0 4