JavaScript中函數定義的三種方法



函數的三種定義方法分別是:函數定義語句、函數直接量表達式和Function()構造函數的方法。下面依次介紹這幾種方法具體怎么實現。

1. 函數定義語句
//求和函數
function sum(a,b){
return a+b;
}
這是最典型的函數聲明,以關鍵字function開始,其后跟隨函數名稱標識符、一對圓括號(包含由0個或多個逗號隔開的參數名稱)和一對花括號(包含0條或多條JS語句,構成函數體)。這種函數定義方式需要顯式的指定函數名稱,在代碼執行前就被解釋器加載到作用域中,這個特性可以讓我們在函數定義之前就調用該函數。我們可以通過代碼來驗證這一點。
console.log(sum); //控制台輸出sum函數的源代碼,此時函數還未定義
function sum(a,b){
return a+b;
}
console.log(sum(2,3)); //5
既然提到函數聲明,就要提到函數的作用域。函數作用域是指在函數內聲明的所有變量在函數體內始終是可見的,這意味着,變量在聲明之前已經可用。這個特性可以被稱為聲明提前,即在函數體內聲明的所有變量,在聲明之前已經有定義,但只有在執行到這個變量時才會被真正賦值。從以代碼可以清晰地看到這一點

var scope = "global";
function f(){
console.log(scope); //輸出“undefined”,而不是“global”
var scope = "local"; //變量在這里賦初始值,但變量本身在函數體內任何地方均是有定義的
console.log(scope); //輸出“local”
}
f();
以上代碼等價於
var scope = "global";
function f() {
var scope; //在函數頂部聲明了局部變量,即聲明提前
console.log(scope); //變量存在,輸出“undefined”,而不是“global”
var scope = "local"; //變量在這里賦初始值
console.log(scope); //輸出“local”
}
f();


2. 函數直接量表達式
//求階乘的函數
var factorial = function fact(x){ //將函數賦值給一個變量
if(x<0) {return NaN;}
else if(x===0) {return 1;}
else
return x*fact(x-1); //遞歸函數
};
console.log(factorial(3)); //6

與函數定義語句一樣,函數直接量表達式也是用到了關鍵字function。一般這種定義方式適用於將它作為一個大的表達式的一部分,比如在賦值和調用過程中定義函數。通過函數直接量生成的函數,函數名稱可以省略,此時就是一個匿名函數。如下例所示:這樣可以使代碼更為緊湊。函數定義表達式特別適合用來定義那些只會用到一次的函數。

var f=function(x){ //省略函數名的匿名函數
return x*x;
}


與函數定義語句不同的是,函數直接量表達式是在執行到代碼時才加載函數的,我們可以用下面的代碼來說明。

console.log(f); //控制台輸出undefined,此時函數f還未加載
var f=function(x){ //開始加載函數
return x*x;
}
console.log(f); //控制台輸出函數的源代碼


3. Function()構造函數
var f = new Function("x","y","return x+y"); //Function()構造函數
var f = function(x,y){return x+y}; //這兩條代碼是等價的

Function()構造函數可以傳入任意數量的字符串實參,最后一個實參所表示的文本是函數體,可以包含任意數量的JavaScript語句。如果構造的函數不包含任何參數,則只需傳入一個函數體即可。與前兩者方式不同的是,Function()構造函數允許JavaScript在運行時動態地創建並翻譯函數。每次調用Function()構造函數都會解析函數體,並創建新的函數對象。因而,在循環或多次調用的函數中執行這個構造函數,執行效率會受影響。相比之下,循環中的嵌套函數和函數定義表達式則不會每次執行時都重新編譯。

Function()構造函數還有值得注意的一點就是它所創建的函數並不是使用詞法作用域,函數體代碼的編譯總在頂層函數執行。如下代碼所示:

var a = 3; //在頂層函數中聲明變量a
function f(){
var a = 2; //在函數體內聲明局部變量a
return new Function("return a*a;"); //無法捕獲局部作用域
}
console.log(f()()); //控制台輸出9而非4,說明構造函數的編譯在頂層函數執行

我們可以將Function()構造函數認為是在全局作用域中執行的eval()。在實際編程中,Function()構造函數很少用到,前兩中定義方法使用比較普遍。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM