一、JavaScript 函數(shù)定義
通過(guò)?function?關(guān)鍵詞定義。
1、函數(shù)聲明
function??functionName(parameters) {??要執(zhí)行的代碼??}
被聲明的函數(shù)不會(huì)直接執(zhí)行,而是在被調(diào)用時(shí)執(zhí)行。一般不以分號(hào)(用于分隔可執(zhí)行的 JavaScript 語(yǔ)句)結(jié)尾。
2、函數(shù)表達(dá)式定義
var x = function (a, b) {return a * b};? ? //函數(shù)表達(dá)式在變量x中保存,此后x可作為函數(shù)(或值)使用。稱之為匿名函數(shù)。
3、Function() 構(gòu)造器——內(nèi)建 JavaScript 函數(shù)構(gòu)造器
var myFunction = new Function("a", "b", "return a * b");? ? //等同于var myFunction = function (a, b) {return a * b};
var x = myFunction(4, 3);? ??
一般避免使用new關(guān)鍵詞。
4、函數(shù)提升
Hoisting 應(yīng)用于變量聲明和函數(shù)聲明。但使用表達(dá)式定義的函數(shù)不會(huì)被提升。
5、自調(diào)用函數(shù)
函數(shù)表達(dá)式可作為自調(diào)用,函數(shù)聲明不可自調(diào)用。
函數(shù)表達(dá)式自動(dòng)執(zhí)行自調(diào)用,只需要在表達(dá)式后加()。若自調(diào)用函數(shù)聲明,則需將整個(gè)函數(shù)聲明用圓括號(hào)括起來(lái)(表示它是一個(gè)函數(shù)表達(dá)式),再添加()。
6、函數(shù)是對(duì)象
typeof?運(yùn)算符為函數(shù)返回 "function",但最好將函數(shù)描述為對(duì)象,有屬性和方法。如arguments.length?方法返回函數(shù)被調(diào)用時(shí)收到的參數(shù)數(shù)目,toString()?方法以字符串返回函數(shù)。
對(duì)象方法:定義為對(duì)象屬性的函數(shù)。
對(duì)象構(gòu)造函數(shù)(對(duì)象構(gòu)造器):為創(chuàng)建新對(duì)象而設(shè)計(jì)的函數(shù)。
二、JavaScript 函數(shù)參數(shù)
函數(shù)不會(huì)對(duì)參數(shù)值進(jìn)行任何檢查。
1、函數(shù)參數(shù)
functionName (?parameter1,parameter2,parameter3?) {??要執(zhí)行的代碼??}
parameter:在函數(shù)定義中列出的名稱——形式參數(shù)。
argument:傳遞到函數(shù)或由函數(shù)接收的真實(shí)值——真實(shí)參數(shù)。
當(dāng)調(diào)用參數(shù)時(shí)參數(shù)省略或少于被聲明的數(shù)量,缺失的值被設(shè)置為:undefined。
2、參數(shù)規(guī)則
函數(shù)定義不會(huì)規(guī)定parameter的數(shù)據(jù)類型。
函數(shù)不會(huì)對(duì)傳遞參數(shù)argument進(jìn)行類型檢查,不會(huì)對(duì)接收參數(shù)argument進(jìn)行數(shù)量檢測(cè)。
3、arguments 對(duì)象——JavaScript內(nèi)置對(duì)象
當(dāng)函數(shù)調(diào)用參數(shù)過(guò)多(超過(guò)聲明),使用arguments對(duì)象達(dá)到參數(shù)。
arguments 對(duì)象包含函數(shù)調(diào)用時(shí)使用的參數(shù)數(shù)組。
4、參數(shù)通過(guò)值傳遞
函數(shù)接受值而非參數(shù)的位置。
函數(shù)改變了參數(shù)的值但不會(huì)改變參數(shù)的原始值。
參數(shù)的改變?cè)诤瘮?shù)之外是不可見(jiàn)的。
5、對(duì)象是由引用傳遞的
函數(shù)改變了對(duì)象屬性也會(huì)改變?cè)贾怠?/p>
對(duì)象屬性的改變?cè)诤瘮?shù)之外是可見(jiàn)的。
三、JavaScript 函數(shù)調(diào)用
調(diào)用函數(shù)有三種方法,應(yīng)用于不同的場(chǎng)景。對(duì)應(yīng)聲明函數(shù)的三種方法:表達(dá)式、對(duì)象方法和函數(shù)構(gòu)造器。
1、以函數(shù)形式調(diào)用函數(shù)
function myFunction(a, b) { return a * b;}? ? ?myFunction(1, 2);//該函數(shù)不屬于任何對(duì)象,屬于全局對(duì)象
全局對(duì)象
在 HTML 中是 HTML 頁(yè)面本身。在瀏覽器中,這個(gè)頁(yè)面對(duì)象就是瀏覽器窗口,函數(shù)自動(dòng)成為一個(gè)窗口函數(shù)。
此時(shí)this關(guān)鍵詞指代的是該全局對(duì)象。
不推薦:因?yàn)槿肿兞俊⒎椒ɑ蚝瘮?shù)容易在全局對(duì)象中產(chǎn)生命名沖突和漏洞。
2、作為方法調(diào)用函數(shù)
fullName: function () {? ?return this.firstName + " " + this.lastName;? ?}? ? ??myobject.fullName();
方法:被定義為對(duì)象屬性的函數(shù)。
this指代的是擁有這個(gè)方法(函數(shù)代碼)的對(duì)象。
以對(duì)象方法來(lái)調(diào)用函數(shù),會(huì)導(dǎo)致?this?的值成為對(duì)象本身。
3.通過(guò)函數(shù)構(gòu)造器調(diào)用函數(shù)
// 這是函數(shù)構(gòu)造器:function? myFunction(arg1, arg2) {? this.firstName = arg1; this.lastName = arg2; }
// 創(chuàng)建了一個(gè)新對(duì)象:var x = new myFunction("Bill", "Gates");? ? ? ? ?x.firstName;
通過(guò)構(gòu)造器調(diào)用函數(shù)時(shí),會(huì)創(chuàng)建新對(duì)象,新對(duì)象從其構(gòu)造器繼承屬性和方法。
構(gòu)造器內(nèi)的?this?關(guān)鍵詞沒(méi)有值,this值會(huì)指代調(diào)用函數(shù)時(shí)創(chuàng)建的新對(duì)象。
四、JavaScript 函數(shù) Call和?Apply
作用均為:方法重用。
1、call()方法
作用:編寫能夠在不同對(duì)象上使用的方法。
call()?方法是JavaScript的預(yù)定義方法,以對(duì)象為參數(shù),將方法應(yīng)用于該對(duì)象的參數(shù)的函數(shù)。

2、Apply()方法
作用:編寫用于不同對(duì)象的方法。
apply()?方法是JavaScript的預(yù)定義方法,以方法擁有者(對(duì)象)為參數(shù),用來(lái)調(diào)用該對(duì)象的方法的函數(shù)。

3、call() 和 apply() 的區(qū)別
call()?方法分別接受參數(shù)。

apply()?方法接受數(shù)組形式的參數(shù)。

4、在數(shù)組上模擬 max 方法
JavaScript 數(shù)組沒(méi)有 max() 方法,可以應(yīng)用?Math.max()?方法。
Math.max.apply(null, [1,2,3]); // 也會(huì)返回 3
Math.max.apply(Math, [1,2,3]); // 也會(huì)返回 3
Math.max.apply(" ", [1,2,3]); // 也會(huì)返回 3
Math.max.apply(0, [1,2,3]); // 也會(huì)返回 3
5、嚴(yán)格模式
嚴(yán)格模式下,如果?apply()?方法的第一個(gè)參數(shù)不是對(duì)象,則它將成為被調(diào)用函數(shù)的所有者(對(duì)象)。在“非嚴(yán)格”模式下,它成為全局對(duì)象。
五、閉包 (Closure)
JavaScript 變量屬于本地(局部變量)或全局(全局變量)作用域。全局變量能夠通過(guò)閉包實(shí)現(xiàn)局部(私有)。
1、變量作用域
局部變量:函數(shù)內(nèi)部定義聲明的變量。在函數(shù)調(diào)用時(shí)創(chuàng)建,在函數(shù)完成后被刪除。
全局變量:不通過(guò)關(guān)鍵詞?var?創(chuàng)建的變量總是全局的,即使它們?cè)诤瘮?shù)中創(chuàng)建?;畹煤蛻?yīng)用程序(窗口、網(wǎng)頁(yè))一樣久。
函數(shù)內(nèi)部可直接讀取函數(shù)內(nèi)部聲明的局部變量和全局變量,在函數(shù)外部無(wú)法讀取函數(shù)內(nèi)的局部變量。
2、如何讀取局部變量?
解決方法:嵌套函數(shù)——在函數(shù)內(nèi)部再定義一個(gè)函數(shù)。

Javascript語(yǔ)言特有的"鏈?zhǔn)阶饔糜?結(jié)構(gòu)(chain scope):子對(duì)象會(huì)一級(jí)一級(jí)地向上尋找所有父對(duì)象的變量。因此,父對(duì)象的所有變量,對(duì)子對(duì)象都是可見(jiàn)的,反之則不成立。
3、閉包的概念
閉包就是能夠讀取其他函數(shù)內(nèi)部變量的函數(shù),即定義在一個(gè)函數(shù)內(nèi)部的函數(shù)。在本質(zhì)上,閉包就是將函數(shù)內(nèi)部和函數(shù)外部連接起來(lái)的一座橋梁。父級(jí)函數(shù)被這個(gè)匿名函數(shù)(子函數(shù))的作用域保護(hù),且僅能由該子函數(shù)修改。父函數(shù)實(shí)現(xiàn)擁有“私有”變量。
作用:讀取函數(shù)內(nèi)部的變量;讓這些變量的值始終保持在內(nèi)存中。
4、使用閉包的注意點(diǎn)
①閉包內(nèi)存消耗大,濫用閉包會(huì)造成網(wǎng)頁(yè)的性能問(wèn)題,在IE中可能導(dǎo)致內(nèi)存泄露。解決方法是,在退出函數(shù)之前,將不使用的局部變量全部刪除。
②閉包會(huì)在父函數(shù)外部改變父函數(shù)內(nèi)部變量的值。因此,如果把父函數(shù)當(dāng)作對(duì)象(object)使用,把閉包當(dāng)作它的公用方法(Public Method),把內(nèi)部變量當(dāng)作它的私有屬性(private value),一定不要隨便改變父函數(shù)內(nèi)部變量的值。