許多傳統的程式語言中,宣告一個函數,通常僅能藉由關鍵字如:private void Click(){....}來聲明並使用,但如果需要將函數作為參數傳給另一個函數,或者賦予給本地變數,甚至是作為一個返回值,是需要藉由pointer、delegate等特殊方式來達成,且較為複雜。
但在Javascript中就不一樣了,不但具有傳統函數的特點,也可以做到像變數一樣,作為參數的傳遞、變數的賦值、返回值等,甚至還可以作為"類"構造函數的作用,因此各種使用方式都有其優缺點在,需要加以了解後才能正確地使用,就以宣告方式來說,就有以下四種常見的宣告方式。
●函數宣告:function declaration(){...}●函數運算式-匿名函數:var functionExpression = function(){....}
●函數運算式-具名函數:var namedFunctionExpression = function named(){....}
●Function類:var functionConstructor = new Function(...)
這些是常看到用來宣告函數的方法,但其中有些差異。
一、函數宣告(Function Declaration)
function fn(){ //content }使用這樣的方式來宣告函數,則同一個作用域內皆可訪問,不論宣告在調用之前或是調用之後,而這是因為在javascript執行前就被建立起來,而非動態產生,且藉由hoisting機制讓其提升到作用域最前面,即使寫代碼的時候在最後面也會被提升至最前面,在該領域的任何地方皆可存取,除此之外這種函數宣告方式又為具名函數,名稱為fn,採具名函數對於Debug是非常有幫助的。
fn();//doSomething
function fn(){
console.log('doSomething');
}
fn();//doSomething
由於屬於靜態的關係,故缺點在於無法根據條件的判斷來決定function的內容。var flag = false; function fn1(){ console.log('fn1') } if (flag) { function fn1(){ console.log('fn1 and flag = true'); } } fn1();原本預期結果因flag = false故條件不成立,會是印出fn1,但實際結果卻是fn1 and flag = true,因此無法根據條件的判斷來決定function內容。
二、函數運算式(Function Expressions)
可以宣告一個變數來動態產生一個function,但須注意的是在執行期間才被建立起來,因此在調用時得確保是否在調用之前就宣告,否則會發生「undefined is not a function」的錯誤,由於是動態產生,所以必須先產生才能調用。
fn();//undefined is not a function var fn = function(){ console.log('doSomething'); } fn();//doSomething這種宣告方式屬於動態宣告,故我們可以加入判斷來決定該function的內容,故可以得知結果為「fn1 and flag = true」。
var flag = true; var fn1 = function(){ console.log('fn1'); }; if (flag) { fn1 = function (){ console.log('fn1 and flag = true'); }; }else{ fn1 = function (){ console.log('fn1 and flag = false'); }; } fn1();
三、具名函數運算式(named function expressions,簡稱 NFE)
上面的宣告方式都是屬於匿名宣告,若想採用具名宣告可參考如下,對於Debug時較有幫助,且假設在function內又要呼叫自己的話可以採取具名方式,這樣一來可讀性較佳。var result = function Fibonacci(n){ return n === 1 ? n : n + Fibonacci(n - 1); }; alert(Fibonacci(100))//這個變數在函數之外是看不到的 alert(result(100)); //1+...+100=5050
四、函數關鍵字(Function Keyword)
直接使用Function關鍵字來建立函數物件,也就是使用new與建構子來建立函數,且不會建立任何的closure,在這個函數中只能存取全域的變數與該函數內部的變數,此外,每一次的執行都會進行parse的動作故效率較差。
var add = new Function('a','b','return a + b;') console.log(add(5+3))//8可以發現參數都是字串,這種建立方式充滿了危險性,尤其是如果參數來自使用者的輸入情況下更加危險。
留言
張貼留言