Javascript Function Invocation
Javascript Function Invocation Patterns 有以下四種方式:
- Method Invocation
- Function Invocation
- Constructor Invocation
- Apply And Call Invocation
為什麼要瞭解這是四個有什麼不同呢?接著看就知道了。
Function Execution
function在執行的範圍內的任何地方都可以被呼叫。當我們呼叫了
function在執行的範圍內的任何地方都可以被呼叫。當我們呼叫了
一個function他就會暫時停止目前的function的執行,並且傳遞參數
和控制的訊息到被呼叫的function。
在呼叫function有不同的方式,但這些不同的方式會產生不一樣的結果作者是認為是在設計javascript時的錯誤。所以最好將這四種方式都瞭解對你在撰寫javascript時才不會太多的問題。
The Four Invocation Patterns
1. Method Invocation
當一個functiion是object的一部分的話,他稱之為方法(method)。
範例:
var obj = { value: 0, increment: function() { this.value+=1; } }; obj.increment(); //Method invocation
increment就是obj的方法,當obj的方法被呼叫後javascript會設定this這個關鍵字指向obj。所以看上面的範例當我們要在increment去讀寫obj的value變數的話,就要寫成this.value。
2. Function Invocation
當我們使用function Invocation的時候,this是被設定為global object而且是指向window object 這是JavaScript設計上的錯誤,一旦不小心寫錯很容易就可以將 global object的內容給破壞掉。
再inner function中這樣的錯誤是很容易出現的,我們可以看一下範例:
var value = 500; //Global variable var obj = { value: 0, increment: function() { this.value++; var innerFunction = function() { alert(this.value); } innerFunction(); //Function invocation pattern } } obj.increment(); //Method invocation pattern
從這個範例來看你認為innerFunction()會跳出怎樣的答案呢?認為是1的話你就錯了正確答案是500。所以inner function是用function invocation的方式來被呼叫,所以this是被設定成global物件,而不是目前的物件。因此inner function中的this.value的值就是500。
如果要解決這個問題,作者也提供了一個範例:
var value = 500; //Global variable var obj = { value: 0, increment: function() { var that = this; that.value++; var innerFunction = function() { alert(that.value); } innerFunction(); //Function invocation pattern } } obj.increment();
就是用變數that來取代this這樣就可以了,為什麼這樣可以呢?因為JavaScript是closures至於closures是什麼呢?可以看一下這個連結http://doctrina.org/JavaScript:Why-Understanding-Scope-And-Closures-Matter.html#closures (有空再來寫什麼是closures)。
3. Constructor Invocation
JavaScript不是標準的物件導向語言,而是原型物件導向語言(prototypical object oriented language) ,在標準的物件導向,物件是類別的實例。在C++跟Java ,實例是藉由new來產生。
JavaScript也是用new來產生,而constructor invocation也是再這個時候會被呼叫,來看個例子吧:
var Cheese = function(type) { var cheeseType = type; return cheeseType; } cheddar = new Cheese("cheddar"); //new object returned, not the type.
儘管Cheese是一個function物件,我們需要利用new來呼叫function來建立一個新的物件。
this將會設定到新的物件上。
1. 假如function回傳一個簡單的型態(像是number,string,boolean,null or undefined),
哪麼回傳的資料將被忽略,取代的是回傳this(新的object)
2. 假如function回傳一個object的實例,那麼接著他會回傳object來取代this
範例:
var obj = { data : "Hello World" } var Func1 = function() { return obj; } var Func2 = function() { return "I am a simple type"; } var f1 = new Func1(); //f1 is set to obj var f2 = new Func2(); //f2 is set to a new object
4. Apply And Call Invocation
apply跟call的使用方式是一樣的,不同是在於傳遞變數時,一個是用陣列另一個是用參數
並且要明確的設定this。
範例1:
var add = function(num1, num2) { return num1+num2; } array = [3,4]; add.apply(null,array); //7
第一個參數設為null(這個function不是object,所以並不需要傳object進去),接著是array傳遞到num1跟num2中(用appay才能這樣做,call不行)
範例2:
var obj = { data:'Hello World' } var displayData = function() { alert(this.data); } displayData(); //undefined displayData.apply(obj); //Hello World
這個範例就看的出來我們可以利用apply來綁住this跟obj來讓我們使用。
留言