2011-09-18 31 views
15

"Hızlı, ilişkisiz sarmalayıcılar" oluşturmak için kullanılan Function.call.apply hack'inin üzerine geldiğimde JavaScript Garden göz gezdiriyordum. Yazıyor:JavaScript'te Function.call.apply işlevinin amacı nedir?

Başka bir hile hem aramayı hem de hızlı, ilişkisiz sarmalayıcılar oluşturmak için birlikte uygulamayı kullanmaktır. Function.apply yeterli olacaktır zaman Function.call.apply kullanarak neden rahatsız

function Foo() {} 

Foo.prototype.method = function(a, b, c) { 
    console.log(this, a, b, c); 
}; 

// Create an unbound version of "method" 
// It takes the parameters: this, arg1, arg2...argN 
Foo.method = function() { 

    // Result: Foo.prototype.method.call(this, arg1, arg2... argN) 
    Function.call.apply(Foo.prototype.method, arguments); 
}; 

Anlamadığım kalmamasıdır. Sonuçta, her ikisi de semantik olarak eşdeğerdir.

+0

[JavaScript Garden] 'a bir bağlantı gönderdim (http://javascriptgarden.info/). Doğrudan gönderiyi içeren bölüme atlamak istiyorsanız, [buraya] tıklayın (http://javascriptgarden.info/#function.arguments). –

+0

tnx, - Bu kesmek biraz hız kazandırdığını ima ettikleri görünüyor .. ama, gerçekten, sadece ** kullanma **. – c69

+2

@Aadit 'Function.call.apply' ve' İşlev.Uygula 'burada aynı olamaz çünkü eski' Function.call 'işlevini yerine getirirken, ikincisi 'Function' yapıcısını uygulamayı dener. Cevabımla ilgili ayrıntılar, ama Ivo Wetzel'in buna cevap vermek için gelmesi durumunda bahse girerim ki çok daha anlaşılır ve anlaşılabilir olurdu. Bu oldukça derin bir şey. Muhtemelen meslektaşlarınızın harcamak istemediğiniz sürece kullanmamanız gereken bir şey olmadığına katılıyorum, bilmiyorum, bir _half saat_ anlamaya çalışıyorum. :) –

cevap

13

Hayır, Function.call.apply ve Function.apply aynı değildir bu durum.

orijinal arayan çağrısı ile

Foo.method(t, x, y, z) 

çağırır söylemek ve JavaScript Bahçe kodda olduğu gibi, birlikte uygulayalım. Bu (dizi-gösterimde arguments yazma, gevşek) olan

Function.call.apply(Foo.prototype.method, arguments); 

yürütür: çağırır

Function.call.apply(Foo.prototype.method, [t, x, y, z]); 

Function.callthis==Foo.prototype.method ile:

t için Foo.prototype.method ile this set aramaları
Foo.prototype.method.call(t, x, y, z) 

ve bağımsız değişkenler x, y ve z. Tatlı. Sadece yorumlarda olduğu gibi. Bir ambalajı başarıyla tamamladık.

Şimdi varsayalım, Function.call.apply yerine sadece Function.apply olduğunu söylediniz. Sen (gevşek) Foo.prototype.method ve argümanlar t, x, y ve z için this seti ile işlevini Function (ugh!) Çağırır

Function.apply(Foo.prototype.method, [t, x, y, z]); 

olan

Function.apply(Foo.prototype.method, arguments); 

olurdu.

Aynı şekilde değil.

+0

Ama böyle bir ambalajlamanın amacı nedir? – c69

+3

Amaç, Foo.prototype.method işlevini 'Foo' örneğine bağlı olmadan çağırmaktır. Bunun yerine, 'foo.prototype.method' içinde' this 'değeri olarak kullanılacak olan kendi_dosyanızdan geçersiniz. Neden bunu yaptın? Belki de bazı fonksiyonel programlama yapmak istersiniz ve haritalamak veya azaltmak veya filtrelemek istediğiniz fonksiyon bağlı bir metot olur. Bir nesneye bağlı kalmak istemiyorsanız, "ilişkisiz bir sarmalayıcı" diyorsunuz. Bu garip bir terminoloji olsa da, nihayetinde bu yöntemi kendi nesnesine bağladığınız için (ama bunu görmezden gelebilirsiniz ....) –

+0

Tamam, anladığım kadarıyla aşağıdaki ifadeler eşdeğerdir: Function.call.apply (Foo.prototype.method, argümanlar); Foo.prototype.method.apply (arguments [0], Array.prototype.slice.call (argümanlar, 1)); Her ikisi de birleştirilmemiş sarmalayıcılar oluşturmak için değiştirilebilir. Bununla birlikte, ilk yöntem daha kısa, daha hızlı ve daha sezgiseldir. Korku veren! –

4

Bu, bir nesnedeki bir nesneyi yöntemleri kullanabileceğiniz anlamına gelir.

iyi bir örnek tüm fonksiyonlar var argümanlar değişkendir, bir dizide gibi ama böylece üzerine dizinin yöntemleri bir dizi çağırabilir o kadar:

Array.prototype.join.call(arguments, ","); 
+1

Peki, orijinal uygulamasında 'apply' biti ne yapar? –

+1

@CameronSkinner: bir işlev nesnesinin 'apply' yöntemi bu işlevi yürütür, ilk argümanı bu yürütmede 'this' olarak ve ikinci argümanı 'argümanlar' olarak ele alır. fn.apply (a, [b, c]) 'fn.call (a, b, c)' ile eşdeğerdir. – eyelidlessness