通俗的來(lái)講,函數(shù)是由事件驅(qū)動(dòng)的或者當(dāng)它被調(diào)用時(shí)執(zhí)行的可重復(fù)使用的代碼快。它是 JavaScript 語(yǔ)言一個(gè)即重要又復(fù)雜的組成部分,任何一個(gè) JavaScript 框架,如 Dojo、jQuery 等都是有成百上千個(gè)函數(shù)組成的。函數(shù)的使用不僅提高了代碼本身的可讀性,也為它的擴(kuò)展提供了可能,同時(shí)還降低了維護(hù)成本,加快 web 項(xiàng)目的開(kāi)放進(jìn)度;尤其是在多人參與的敏捷開(kāi)發(fā)中。
通常函數(shù)的定義是通過(guò) function 語(yǔ)句實(shí)現(xiàn)的:
清單 1.函數(shù)定義
funcname 是要定義的函數(shù)名,是一個(gè)標(biāo)識(shí)符,而不是字符串或者表達(dá)式;緊跟函數(shù)名后面的是用括號(hào)括起來(lái)的參數(shù)列表,參數(shù)之間用逗號(hào)隔開(kāi);最后,也是這個(gè)函數(shù)的核心部分:函數(shù)體,它是由一行或者多行代碼組成并且是用大括號(hào)括起來(lái)的。
函數(shù)定義描述的是一個(gè)靜態(tài)的程序結(jié)構(gòu),當(dāng) JavaScript 解析器遇到一個(gè)函數(shù)定義時(shí),它就被解析并存儲(chǔ)構(gòu)成函數(shù)體的語(yǔ)句,然后定義一個(gè)和該函數(shù)名同名的全局或者某個(gè)對(duì)象屬性來(lái)保存。當(dāng)該函數(shù)被調(diào)用時(shí),里面的函數(shù)體才真正的被執(zhí)行。如:
清單 2
定義一個(gè)函數(shù),最為普遍的是直接使用 function 關(guān)鍵字來(lái)定義,又稱函數(shù)聲明式(function declaration),如上面定義的 f 函數(shù),但是 function 語(yǔ)句并非是定義函數(shù)的惟一方法。在 ECMAScript v1 和 JavaScript v1.1 中,還可以使用 Function () 構(gòu)造函數(shù)和 new 運(yùn)算符動(dòng)態(tài)地定義函數(shù),如下:
var myfunc=new Function ('x', 'y', 'alert(x+y)');
這行代碼創(chuàng)建了一個(gè)新函數(shù),該函數(shù)和下面使用 function 方法定義的函數(shù)是等價(jià)的:
清單 3.
Function () 定義中,前面兩個(gè)是參數(shù),參數(shù)可以是任意多個(gè)字符串;第三個(gè)是函數(shù)體,可以包含任何 JavaScript 語(yǔ)句,語(yǔ)句之間用分號(hào)隔開(kāi)。如果沒(méi)有參數(shù),傳一個(gè)函數(shù)體即可。由于傳遞給 Function () 函數(shù)中,沒(méi)有一個(gè)字符串是用來(lái)聲明函數(shù)名的,所以它是一個(gè)匿名函數(shù)。
使用 Function()構(gòu)造函數(shù)來(lái)定義函數(shù)允許我們動(dòng)態(tài)的來(lái)定義和編譯一個(gè)函數(shù),而不是限定在 function 預(yù)編譯的函數(shù)體中。但同時(shí)也會(huì)帶來(lái)負(fù)面影響,因?yàn)槊看握{(diào)用這個(gè)函數(shù)都要對(duì)它進(jìn)行編譯,對(duì)性能有一定的影響,尤其是在循環(huán)體中。
函數(shù)定義的第三種方式是函數(shù)直接量,ECMAScript v3 定義了函數(shù)直接量,JavaScript 1.2 實(shí)現(xiàn)了它。函數(shù)直接量是一個(gè)表達(dá)式,它即可以定義一個(gè)匿名函數(shù),也可以定義一個(gè)帶函數(shù)名的函數(shù):
清單 4.
注意:調(diào)用時(shí)得用定義的變量名,如f(4),而不能fact(4).
函數(shù)直接量和使用 Function()構(gòu)造函數(shù)來(lái)創(chuàng)建函數(shù)的方法非常相似,因?yàn)閮煞N方法都是通過(guò) JavaScript 的表達(dá)式創(chuàng)建的,而不是由語(yǔ)句創(chuàng)建的;所以使用他們的方式也更靈活,尤其是那些只使用一次,而且不需要命名的函數(shù)。比如把它傳遞給其他的函數(shù):
清單 5.
三種方式的區(qū)別,可以從作用域、效率以及加載順序來(lái)區(qū)分。首先,從作用域上來(lái)說(shuō),函數(shù)聲明式和函數(shù)直接量使用的是局部變量,而 Function()構(gòu)造函數(shù)卻是全局變量:
清單 6.
其次是執(zhí)行效率上來(lái)說(shuō),F(xiàn)unction()構(gòu)造函數(shù)的效率要低于其他兩種方式,尤其是在循環(huán)體中,因?yàn)闃?gòu)造函數(shù)每執(zhí)行一次都要重新編譯,并且生成新的函數(shù)對(duì)象:
清單 7.
由此可見(jiàn),在循環(huán)體中,函數(shù)直接量的執(zhí)行效率是 Function()構(gòu)造函數(shù)的 0.6 倍。所以在 Web 開(kāi)發(fā)中,為了加快網(wǎng)頁(yè)加載速度,提高用戶體驗(yàn),我們不建議選擇 Function ()構(gòu)造函數(shù)方式來(lái)定義函數(shù)。
最后是加載順序,function 方式(即函數(shù)聲明式)是在 JavaScript 編譯的時(shí)候就加載到作用域中,而其他兩種方式則是在代碼執(zhí)行的時(shí)候加載,如果在定義之前調(diào)用它,則會(huì)返回 undefined:
清單 8.
當(dāng)深入 JavaScript 編程世界時(shí),您將遇到的基本概念之一是方法和函數(shù)之間的區(qū)別。雖然方法和函數(shù)在 JavaScript 中都起著至關(guān)重要的作用,但它們具有不同的目的并以不同的方式使用。在這篇博文中,我們將揭開(kāi)這兩個(gè)概念的神秘面紗,讓您清楚地了解它們的差異。
讓我們深入了解有關(guān) function 和 method 的更多詳細(xì)信息:
function 的核心是執(zhí)行特定任務(wù)或一組任務(wù)的可重用代碼塊。將其視為一組預(yù)定義的指令,您可以在需要時(shí)調(diào)用或調(diào)用它們。函數(shù)就像 JavaScript 代碼的構(gòu)建塊,允許您將復(fù)雜的任務(wù)分解為更小的、可管理的部分。
這是一個(gè)函數(shù)的基本示例:
function greet(name) {
return "Hello, " + name + "!";
}
在此代碼段中, greet 是一個(gè)函數(shù),它采用單個(gè)參數(shù) name ,并返回問(wèn)候語(yǔ)字符串。 JavaScript 中的函數(shù)用途廣泛,可以在各種上下文中使用,從像這樣的簡(jiǎn)單操作到復(fù)雜的邏輯。
現(xiàn)在,我們來(lái)談?wù)劮椒ā?JavaScript 中的方法本質(zhì)上是一個(gè)函數(shù),但有一個(gè)關(guān)鍵的區(qū)別——它與一個(gè)對(duì)象關(guān)聯(lián)。方法是存儲(chǔ)為對(duì)象屬性的函數(shù),用于定義該對(duì)象的行為。下面舉個(gè)例子來(lái)說(shuō)明:
let person={
firstName: "John",
lastName: "Doe",
fullName: function() {
return this.firstName + " " + this.lastName;
}
};
在此示例中, fullName 是 person 對(duì)象的方法。它使用 this 關(guān)鍵字來(lái)訪問(wèn)對(duì)象的屬性。
讓我們重點(diǎn)介紹 JavaScript 中函數(shù)和方法之間的主要區(qū)別:
理解 JavaScript 中 methods 和 functions 之間的區(qū)別對(duì)于編寫(xiě)清晰高效的代碼至關(guān)重要。函數(shù)提供了模塊化和可重用性,而方法則為我們提供了一種遵循面向?qū)ο缶幊淘瓌t將行為封裝在對(duì)象內(nèi)的方法。
總之,雖然所有方法都是函數(shù),但并非所有函數(shù)都是方法。區(qū)別在于它們與對(duì)象的關(guān)聯(lián)以及它們?nèi)绾卧谶@些對(duì)象的上下文中使用。
JavaScript 函數(shù)有 4 種調(diào)用方式。
每種方式的不同方式在于 this 的初始化。
this 關(guān)鍵字
一般而言,在Javascript中,this指向函數(shù)執(zhí)行時(shí)的當(dāng)前對(duì)象。
注意 this 是保留關(guān)鍵字,你不能修改 this 的值。 |
調(diào)用 JavaScript 函數(shù)
我們知道如何創(chuàng)建函數(shù)。
函數(shù)中的代碼在函數(shù)被調(diào)用后執(zhí)行。
作為一個(gè)函數(shù)調(diào)用
實(shí)例
function myFunction(a, b) {
return a * b;
}
myFunction(10, 2); // myFunction(10, 2) 返回 20
以上函數(shù)不屬于任何對(duì)象。但是在 JavaScript 中它始終是默認(rèn)的全局對(duì)象。
在 HTML 中默認(rèn)的全局對(duì)象是 HTML 頁(yè)面本身,所以函數(shù)是屬于 HTML 頁(yè)面。
在瀏覽器中的頁(yè)面對(duì)象是瀏覽器窗口(window 對(duì)象)。以上函數(shù)會(huì)自動(dòng)變?yōu)?window 對(duì)象的函數(shù)。
myFunction() 和 window.myFunction() 是一樣的:
實(shí)例
function myFunction(a, b) {
return a * b;
}
window.myFunction(10, 2); // window.myFunction(10, 2) 返回 20
這是調(diào)用 JavaScript 函數(shù)常用的方法, 但不是良好的編程習(xí)慣 全局變量,方法或函數(shù)容易造成命名沖突的bug。 |
全局對(duì)象
當(dāng)函數(shù)沒(méi)有被自身的對(duì)象調(diào)用時(shí), this 的值就會(huì)變成全局對(duì)象。
在 web 瀏覽器中全局對(duì)象是瀏覽器窗口(window 對(duì)象)。
該實(shí)例返回 this 的值是 window 對(duì)象:
實(shí)例
function myFunction() {
return this;
}
myFunction(); // 返回 window 對(duì)象
函數(shù)作為全局對(duì)象調(diào)用,會(huì)使 this 的值成為全局對(duì)象。使用 window 對(duì)象作為一個(gè)變量容易造成程序崩潰。 |
函數(shù)作為方法調(diào)用
在 JavaScript 中你可以將函數(shù)定義為對(duì)象的方法。
以下實(shí)例創(chuàng)建了一個(gè)對(duì)象 (myObject), 對(duì)象有兩個(gè)屬性 (firstName 和 lastName), 及一個(gè)方法 (fullName):
實(shí)例
var myObject={
firstName:"John",
lastName: "Doe",
fullName: function () {
return this.firstName + " " + this.lastName;
}
}
myObject.fullName(); // 返回 "John Doe"
fullName 方法是一個(gè)函數(shù)。函數(shù)屬于對(duì)象。 myObject 是函數(shù)的所有者。
this對(duì)象,擁有 JavaScript 代碼。實(shí)例中 this 的值為 myObject 對(duì)象。
測(cè)試以下!修改 fullName 方法并返回 this 值:
實(shí)例
var myObject={
firstName:"John",
lastName: "Doe",
fullName: function () {
return this;
}
}
myObject.fullName(); // 返回 [object Object] (所有者對(duì)象)
函數(shù)作為對(duì)象方法調(diào)用,會(huì)使得 this 的值成為對(duì)象本身。 |
使用構(gòu)造函數(shù)調(diào)用函數(shù)
如果函數(shù)調(diào)用前使用了 new 關(guān)鍵字, 則是調(diào)用了構(gòu)造函數(shù)。
這看起來(lái)就像創(chuàng)建了新的函數(shù),但實(shí)際上 JavaScript 函數(shù)是重新創(chuàng)建的對(duì)象:
實(shí)例
// 構(gòu)造函數(shù):
function myFunction(arg1, arg2) {
this.firstName=arg1;
this.lastName=arg2;
}
// Thiscreates a new object
var x=new myFunction("John","Doe");
x.firstName; // 返回 "John"
構(gòu)造函數(shù)的調(diào)用會(huì)創(chuàng)建一個(gè)新的對(duì)象。新對(duì)象會(huì)繼承構(gòu)造函數(shù)的屬性和方法。
構(gòu)造函數(shù)中 this 關(guān)鍵字沒(méi)有任何的值。this 的值在函數(shù)調(diào)用時(shí)實(shí)例化對(duì)象(new object)時(shí)創(chuàng)建。 |
作為函數(shù)方法調(diào)用函數(shù)
在 JavaScript 中, 函數(shù)是對(duì)象。JavaScript 函數(shù)有它的屬性和方法。
call() 和 apply() 是預(yù)定義的函數(shù)方法。 兩個(gè)方法可用于調(diào)用函數(shù),兩個(gè)方法的第一個(gè)參數(shù)必須是對(duì)象本身。
實(shí)例
function myFunction(a, b) {
return a * b;
}
myFunction.call(myObject, 10, 2); // 返回 20
實(shí)例
function myFunction(a, b) {
return a * b;
}
myArray=[10,2];
myFunction.apply(myObject, myArray); // 返回 20
兩個(gè)方法都使用了對(duì)象本身作為第一個(gè)參數(shù)。 兩者的區(qū)別在于第二個(gè)參數(shù): apply傳入的是一個(gè)參數(shù)數(shù)組,也就是將多個(gè)參數(shù)組合成為一個(gè)數(shù)組傳入,而call則作為call的參數(shù)傳入(從第二個(gè)參數(shù)開(kāi)始)。
在 JavaScript 嚴(yán)格模式(strict mode)下, 在調(diào)用函數(shù)時(shí)第一個(gè)參數(shù)會(huì)成為 this 的值, 即使該參數(shù)不是一個(gè)對(duì)象。
在 JavaScript 非嚴(yán)格模式(non-strict mode)下, 如果第一個(gè)參數(shù)的值是 null 或 undefined, 它將使用全局對(duì)象替代。
通過(guò) call() 或 apply() 方法你可以設(shè)置 this 的值, 且作為已存在對(duì)象的新方法調(diào)用。 |
如您還有不明白的可以在下面與我留言或是與我探討QQ群308855039,我們一起飛!
*請(qǐng)認(rèn)真填寫(xiě)需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。