首頁 web前端 js教程 深入理解JavaScript中的函數

深入理解JavaScript中的函數

Dec 15, 2016 am 10:29 AM

函數是進行模組化程式設計的基礎,編寫複雜的Ajax應用程序,必須對函數有更深入的了解。 JavaScript中的函數不同於其他的語言,每個函數都是作為一個物件被維護和運行的。透過函數物件的性質,可以很方便的將一個函數賦值給一個變數或將函數傳遞為參數。在繼續講述之前,先來看看函數的使用語法:

function func1(…){…}
var func2=function(…){…};
var func3=function func4(…){…};
var func5=new Function();
  這些都是宣告函數的正確語法。它們和其他語言中常見的函數或先前介紹的函數定義方式有著很大的差異。那麼在JavaScript中為什麼可以這麼寫呢?它所遵循的語法是什麼呢?下面將介紹這些內容。

  認識函數物件(Function Object)

  可以用function關鍵字定義一個函數,並為每個函數指定一個函數名,透過函數名稱來進行呼叫。當JavaScript解釋執行時,函數都是被維護為一個對象,這就是要介紹的函數物件(Function Object)。

  函數物件與其他使用者所定義的物件有著本質上的區別,這一類物件稱為內部對象,例如日期物件(Date)、陣列物件(Array)、字串物件(String)都屬於內部物件。這些內建物件的建構器是由JavaScript本身定義的:透過執行new Array()這樣的語句傳回一個對象,JavaScript內部有一套機制來初始化傳回的對象,而不是由使用者來指定物件的建構方式。

  在JavaScript中,函數物件對應的類型是Function,正如陣列物件對應的類型是Array,日期物件對應的類型是Date一樣,可以透過new Function()來建立一個函數對象,也可以透過function關鍵字來創建一個物件。為了便於理解,我們比較函數物件的創建和數組物件的創建。先看陣列物件:下面兩行程式碼都是建立一個陣列物件myArray:

var myArray=[];
//等價於
var myArray=new Array();
同樣,下面的兩段程式碼也都是建立一個函數myFunction:
function myFunction(a,b){
      return a+b;
}
//等價於
var myFunction=new Function("a","b","re​​turn a+bvar myFunction=new Function("a","b","re​​turn a+b"," );
  透過和建構數組物件語句的比較,可以清楚的看到函數物件本質,前面介紹的函數宣告是上述程式碼的第一種方式,而在解釋器內部,當遇到這種語法時,就會自動建構一個Function對象,將函數當作一個內部的物件來儲存和運作。從這裡也可以看到,一個函數物件名稱(函數變數)和一個普通變數名稱具有相同的規範,都可以透過變數名稱來引用這個變量,但是函數變數名稱後面可以跟上括號和參數列表來進行函數調用。

  用new Function()的形式來建立一個函數不常見,因為一個函數體通常會有多條語句,如果將它們以一個字串的形式作為參數傳遞,程式碼的可讀性差。以下介紹一下其使用語法:

var funcName=new Function(p1,p2,,pn,body);
  參數的類型都是字串,p1到pn表示所創建函數的參數名稱列表,body表示所創建函數的函數體語句,funcName就是所建立函數的名稱。可以不指定任何參數來建立一個空函數,不指定funcName建立一個無名函數,當然那樣的函數沒有任何意義。

  需要注意的是,p1到pn是參數名稱的列表,即p1不僅能代表一個參數,它也可以是一個逗號隔開的參數列表,例如下面的定義是等價的:

new Function( "a", "b", "c", "return a+b+c")
new Function("a, b, c", "return a+b+c")
new Function("a,b ", "c", "return a+b+c")
  JavaScript引入Function類型並提供new Function()這樣的語法是因為函數物件添加屬性和方法就必須藉助於Function這個類型。
函數的本質是一個內部對象,由JavaScript解釋器決定其運作方式。透過上述程式碼所建立的函數,在程式中可以使用函數名進行呼叫。本節開頭列出的函數定義問題也得到了解釋。注意可直接在函數宣告後面加上括號就表示建立完成後立即進行函數調用,例如:

var i=function (a,b){
       return a+b;
}(1,2);
alert   return a+b;
}(1,2);

alert   return a+b;

}(1,2);

alert   return a+b;🎜}(1,2);🎜alert   return a+b;🎜}(1,2);🎜alert   return a+b;🎜}(1,2); (i);🎜  這段程式碼會顯示變數i的值等於3。 i是表示傳回的值,而不是建立的函數,因為括號「(」比等號「=」有更高的優先權。這樣的程式碼可能不常用,但當使用者想在很長的程式碼段中進行模組化設計或想避免命名衝突,這是一個不錯的解決方法。

function funcName(){
       //函數體
}
//等價於
var funcName=function(){
     //了一個無名函數,只是讓一個變數指向了這個無名函數。在使用上僅有一點區別,就是:對於有名函數,它可以出現在呼叫之後再定義;而對於無名函數,它必須是在呼叫之前就已經定義。例如:

<script language="JavaScript" type="text/javascript">

<!--

func();
var func=function(){
    
</script>
  這段語句將產生func未定義的錯誤,而:

<script language="JavaScript" type="text/javascript">
<!--
func(); ){

      alert(1)

}
//-->
</script>
  則能夠正確執行,下面的語句也能正確執行:

< >
<!--
func();
var someFunc=function func(){

      alert(1)

}
//-->
</script</script型的語言,但它會在函數呼叫時,檢查整個程式碼中是否存在對應的函數定義,這個函數名稱只有是透過function funcName()形式定義的才會有效,而不能是匿名函數。

  函數物件和其他內部物件的關係

  除了函數對象,還有很多內部對象,例如:Object、Array、Date、RegExp、Math、Error。這些名稱實際上表示一個類型,可以透過new操作符傳回一個物件。然而函數物件和其他物件不同,當用typeof得到一個函數物件的類型時,它仍然會傳回字串“function”,而typeof一個陣列物件或其他的物件時,它會傳回字串“object”。下面的程式碼範例了typeof不同類型的情況:

 

alert(typeof(Function)));

alert(typeof(new Function()));

alert(typeof(Array));

alert(typeof( Object));

alert(typeof(new Array()));

alert(typeof(new Date()));

alert(typeof(new Object()));

  運行這段程式碼可以發現:前面4條語句都會顯示“function”,而後面3條語句則顯示“object”,可見new一個function實際上是傳回一個函數。這與其他的對像有很大的不同。其他的型別Array、Object等都會透過new操作符傳回一個普通物件。儘管函數本身也是一個對象,但它與普通的對象還是有區別的,因為它同時也是對象構造器,也就是說,可以new一個函數來返回一個對象,這在前面已經介紹。所有typeof回傳「function」的物件都是函數物件。也稱這樣的對象為構造器(constructor),因而,所有的構造器都是對象,但不是所有的對像都是構造器。

  既然函數本身也是一個對象,它們的類型是function,聯想到C++、Java等物件導向語言的類別定義,可以猜測到Function類型的作用所在,那就是可以為函數物件本身定義一些方法和屬性,借助於函數的prototype對象,可以很方便地修改和擴充Function類型的定義,例如下面擴展了函數類型Function,為其增加了method1方法,作用是彈出對話框顯示"function":

Function.prototype. method1=function(){
      alert("function(){
      alert("function");
}

function func1(a,b,c){

      return a+b+c;

}method1. ();

  注意最後一個語句:func1.method1.mehotd1(),它呼叫了method1這個函數物件的method1方法。雖然看起來有點容易混淆,但仔細觀察一下文法還是很明確的:這是一個遞歸的定義。因為method1本身也是函數,所以它同樣具有函數物件的屬性和方法,所有對Function類型的方法擴充都具有這樣的遞歸性質。

  Function是所有函數物件的基礎,而Object則是所有物件(包含函數物件)的基礎。在JavaScript中,任何一個物件都是Object的實例,因此,可以修改Object這個類型來讓所有的物件有一些通用的屬性和方法,修改Object型別是透過prototype來完成的:

Object.prototype.getType =function(){
       return typeof(this);
}
var array1=new Array();
function func1(a,b){

  

alert(func1.getType());

  上面的程式碼為所有的物件增加了getType方法,作用是傳回該物件的型別。兩個alert語句分別會顯示「object」和「function」。


  將函數作為參數傳遞

  在前面已經介紹了函數對象本質,每個函數都被表示為一個特殊的對象,可以方便的將其賦值給一個變量,再通過這個變量名進行函數調用。作為一個變量,它可以以參數的形式傳遞給另一個函數,這在前面介紹JavaScript事件處理機制中已經看到過這樣的用法,例如下面的程式將func1作為參數傳遞給func2:

function func1( theFunc){
      theFunc();
}
function func2(){
      alert("ok");
}
func1(func2);〔2);㟀句中給了一個字句加號theFunc,再由func1內部進行theFunc的呼叫。事實上,將函數當作參數傳遞,或是將函數賦值給其他變數是所有事件機制的基礎。

  例如,如果需要在頁面載入時進行一些初始化工作,可以先定義一個init的初始化函數,再透過window.onload=init;語句將其綁定到頁面載入完成的事件。這裡的init就是函數對象,它可以加入window的onload事件清單。

以上就是深入理解JavaScript中的函數的內容,更多相關文章請關注PHP中文網(www.php.cn)!


本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

golang函數動態建立新函數的技巧 golang函數動態建立新函數的技巧 Apr 25, 2024 pm 02:39 PM

Go語言提供了兩種動態函數創建技術:closures和反射。 closures允許存取閉包作用域內的變量,而反射可使用FuncOf函數建立新函數。這些技術在自訂HTTP路由器、實現高度可自訂的系統和建置可插拔的元件方面非常有用。

C++ 函數命名中參數順序的考慮 C++ 函數命名中參數順序的考慮 Apr 24, 2024 pm 04:21 PM

在C++函數命名中,考慮參數順序至關重要,可提高可讀性、減少錯誤並促進重構。常見的參數順序約定包括:動作-物件、物件-動作、語意意義和遵循標準函式庫。最佳順序取決於函數目的、參數類型、潛在混淆和語言慣例。

excel函數公式大全 excel函數公式大全 May 07, 2024 pm 12:04 PM

1. SUM函數,用於對一列或一組單元格中的數字進行求和,例如:=SUM(A1:J10)。 2、AVERAGE函數,用於計算一列或一組儲存格中的數字的平均值,例如:=AVERAGE(A1:A10)。 3.COUNT函數,用於計算一列或一組單元格中的數字或文字的數量,例如:=COUNT(A1:A10)4、IF函數,用於根據指定的條件進行邏輯判斷,並返回相應的結果。

如何在Java中寫出高效和可維護的函數? 如何在Java中寫出高效和可維護的函數? Apr 24, 2024 am 11:33 AM

編寫高效且可維護的Java函數的關鍵在於:保持簡潔。使用有意義的命名。處理特殊情況。使用適當的可見性。

C++ 函式預設參數與可變參數的優缺點比較 C++ 函式預設參數與可變參數的優缺點比較 Apr 21, 2024 am 10:21 AM

C++函數中預設參數的優點包括簡化呼叫、增強可讀性、避免錯誤。缺點是限制靈活性、命名限制。可變參數的優點包括無限彈性、動態綁定。缺點包括複雜性更高、隱式型別轉換、除錯困難。

C++ 函式回傳參考型別有什麼好處? C++ 函式回傳參考型別有什麼好處? Apr 20, 2024 pm 09:12 PM

C++中的函數傳回參考類型的好處包括:效能提升:引用傳遞避免了物件複製,從而節省了記憶體和時間。直接修改:呼叫方可以直接修改傳回的參考對象,而無需重新賦值。程式碼簡潔:引用傳遞簡化了程式碼,無需額外的賦值操作。

自訂 PHP 函數和預定義函數之間有什麼區別? 自訂 PHP 函數和預定義函數之間有什麼區別? Apr 22, 2024 pm 02:21 PM

自訂PHP函數與預定義函數的差異在於:作用域:自訂函數僅限於其定義範圍,而預定義函數可在整個腳本中存取。定義方式:自訂函數使用function關鍵字定義,而預先定義函數則由PHP核心定義。參數傳遞:自訂函數接收參數,而預先定義函數可能不需要參數。擴充性:自訂函數可以根據需要創建,而預定義函數是內建的且無法修改。

C++ 函式異常進階:客製化錯誤處理 C++ 函式異常進階:客製化錯誤處理 May 01, 2024 pm 06:39 PM

C++中的異常處理可透過自訂異常類別增強,提供特定錯誤訊息、上下文資訊以及根據錯誤類型執行自訂操作。定義繼承自std::exception的異常類,提供特定的錯誤訊息。使用throw關鍵字拋出自訂異常。在try-catch區塊中使用dynamic_cast將捕獲到的異常轉換為自訂異常類型。在實戰案例中,open_file函數會拋出FileNotFoundException異常,捕捉並處理該異常可提供更具體的錯誤訊息。

See all articles