2009-12-29 105 views
6

什麼是在Javascript應用調用模式參考函數調用模式以及如何使用它適用模式? 使用這種調用模式有什麼好處。如何實現在Javascript

回答

24

採用apply是有關功能上下文(this關鍵字)和參數傳遞。

首先,我想你應該知道在什麼情況下該this關鍵字隱含集:

1 - 當一個函數被調用的方法(函數被調用爲對象的成員):

obj.method(); // 'this' inside method will refer to obj 

2-甲正常的函數調用:

myFunction(); // 'this' inside the function will refer to the Global object 
// or 
(function() {})(); 

-3-當new運算符用於:

var obj = new MyObj(); // this will refer to a newly created object. 

下面是當applycall來,這些方法讓你設置明確情況下,當你調用一個函數,例如:

function test(a) { 
    alert(this + a); 
} 

test.call('Hello', ' world!'); 

在上面的代碼當test功能稱爲this關鍵字設置到字符串('Hello'),以及使所述a參數(' world.')。

兩者,callapply變化所調用的函數內的執行功能(this關鍵字)的上下文中,但它們之間差別是與apply,則可以發送一個數組或數組狀物體作爲要執行的函數的參數,這是非常有用的,例如:

function sum() { 
    var result = 0; 
    for (var i = 0; i < arguments.length; i++) { 
    result += arguments[i]; 
    } 
    return result; 
} 

var args = [1,2,3]; 
sum.apply(null, args); // will return 6 

這可以避免一些非常哈克,(共同)eval調用,如:

如果您有數字Array

var max = Math.max(2,4,6,8); // 8 

但什麼:10

eval('sum(' + args.join() +')'); 

另一個例子中,Math.maxMath.min方法,這些方法可以接收參數一樣任意數量?

var numbers = [2,4,6,8]; 
numbers.push(10); 
var max = Math.max.apply(null, numbers); // 10 

還要注意的是,當nullundefined用作this參數與callapply,所述this對象將參照全局對象(類似於情形#2,正常功能調用)。

對於Math.max例如,上下文是不是真的有關,因爲它們就像「靜態」方法,該this關鍵詞未在內部使用...

+3

+1非常好! ---- – 2009-12-29 18:27:00

+0

啊我想我現在明白了。我錯過的全部觀點是「這是作爲第一個參數提供的價值」。現在,爲什麼我們想將應用方法區分爲單獨的調用類型,這是有道理的。 那麼什麼是差異。通話和應用關鍵字之間呢? – Priyank 2009-12-29 18:30:41

+0

@cms +1完美打印! – 2011-12-11 16:11:37

0

我不知道任何設計名爲「應用模式」的模式,所以我並不認爲這與設計模式完全相關。然而,在JavaScript中有一個函數對象的應用方法(以及相應的調用方法),所以我將解釋這些方法。

apply和call方法基本上允許一個對象從另一個對象中「竊取」一個方法。你會發現,在JavaScript中,方法非常遲到:在調用時。只有在調用方法時,才能解決'this'的值。在通常的方法調用:

some_object.do_something(); 

在do_something的'this'關鍵字引用some_object。申請並致電,讓您重新分配'this'。例如:

some_object.do_something.apply(another_object); 

'this' do_something now中的關鍵字指的是another_object。所以你在another_object上調用屬於some_object的do_something方法。

現在,這是有趣的,但爲什麼會有人想這樣做?這就是爲什麼這是非常有用的一個具體的例子:

// say you want to get some DIVs in the document, you can get all of them with: 
var some_divs = document.getElementsByTagName('DIV'); 

// say you want the third to fifth DIV in the document, some_divs looks like an 
// array so you might think you can slice it, but it's not. It's a collection 
// of elements that fakes being an array and doesn't implement the slice method. 

// No worries, we can steal the slice method from an array 
// and apply it to some_divs: 
var wanted_divs = [].slice.apply(some_divs,[2,5]); 

// Alternatively: 
var wanted_divs = [].slice.call(some_divs,2,5); 

還有另一種使用情況適用的是之間如何應用和呼叫作品差異的結果。如果你把所有的參數在數組和函數需要單個參數,您可以使用適用於傳遞數組和具備的功能看不到陣列作爲單獨的參數的內容:

function some_function (first,second) { 
    alert(first+second); 
} 
var argument_array = ['hello','world']; 
some_function.apply(null, argument_array); 
1

您還可以使用呼叫/申請繼承。

function Client (id) { 
    this.id = id; 
    this.name = "Client" + id; 
} 

Client.prototype = { 
    constructor: Client 

    , toString: function() { 
     return this.name; 
    } 
}; 

function WebClient (id) { 
    Client.call (this, id); 
} 

WebClient.prototype = new Client(); 

WebClient.prototype.constructor = WebClient; 

WebClient.prototype.ping = function() { 
    // do stuff 
}; 

通知Client.call (this, id);此使用this實例,一個new WebClient會造成執行Client。因此,當

this.id = id; 
    this.name = "Client" + id; 

在內部Client執行WebClient實例得到分配的那些屬性。