2009-10-25 17 views
6

Değişken sayıda parametre kabul eden ve bu parametrelerin tümünü diğer anonim işlevlere ileten Javascript işlevini nasıl yazarım?Değişken sayıdaki parametreyi kabul eden ve "ileten" bir JS işlevi nasıl yazılır?

Örneğin

, bir etkinliği tetikleyen bir yöntemin senaryoyu düşünün: Ben bu yangın yöntemleri üreten bir olay fabrikası var Özellikle de

function fireStartedEvent(a,b,c,d,e,f,g,...) { 
    for(var i = 0; i < startedListeners.length; i++) { 
     startedListeners[i](a,b,c,d,e,f,g,...); 
    } 
} 

, bu yöntemler, belirli bir kaç parametreleri bilerek hiçbir ilgisi olay veya işleyicileri tüketir. Bu yüzden şu anda 7'de sabit bir kablo var (bir g arası). Eğer daha azsa, sorun değil. Dahası, kesiliyorlar. tüm parametrelerini nasıl yakalayıp geçirebilirim?

Teşekkürler.

(jQuery veya başka herhangi bir Javascript çerçevesinden kullanılması burada bir seçenek değildir.)

+0

o JavaScript'inizin bir dizi olarak parametrelerini geçirmek mümkün mü? Bu yapabilirdi. – Cyclone

cevap

8

Çözme bu iki JavaScript kavramların bilgisi gerektirir.

Birincisi, işlev argümanlarına adlarını bilmeden erişmek için kullanılabilecek özel bir arguments yerel değişkendir ve bir Array gibi çalışır. Bununla birlikte, arguments bir Arraydeğildir, ancak "gibi bir dizi" bir - nesne - n işleve argümanlar sayısı ve length özelliği olduğu, özelliklere sahip olan 0..n-1 adlandırılır. Basit bir gösteri kullanımı olabilir:

function f (a) { // can include names still, if desired 
    // arguments instanceof Array -> false (exceptions to this?) 
    var firstArg = arguments[0] 
    // a === firstArg -> always true 
    // iterate all arguments, just as if it were an Array: 
    for (var i = 0; i < arguments.length; i++) { 
     alert(i + " : " + arguments[i]) 
    } 
} 
f("a","b","c") 

ikinci bir özelliği, bir "gibi Dizi" teriminin genişleme sonucu bağımsız değişken ile (denir this) belirli bir bağlamda bir fonksiyonu çağırmak olacak Function.apply olduğu nesne. Ancak bkz..

Bu nedenle, araya koyarak:


ECMAScript özellikleri yalnızca nesne, bir "gibi bir dizi" çağrısı da

function fireStartedEvent() { 
    for(var i = 0; i < startedListeners.length; i++) { 
     // jQuery will often pass in "cute" things, such as a element clicked 
     // as the context. here we just pass through the current context, `this`, 
     // as well as the arguments we received. 
     var arg = Array.prototype.slice.call(arguments) 
     startedListeners[i].apply(this, args) 
    } 
} 
, Function.apply etmez evrensel bir "gibi bir dizi" çalışmak Nesne ve ortak uygulamalar bir dizi , uygun bir Array nesnesini gerektirir. Function.apply bağlantıdan uyarı:

Not: hala nesneler gibi diziyi kabul etmiyoruz ve bir istisna [olmayan bir Array nesnesi eğer fırlatır, Krom 14 ve Internet Explorer 9dahil Çoğu tarayıcı, geçti]. [FireFox, sürüm 4'te giderilmiştir.

var args = Array.prototype.slice.call(arguments); 
:]

Neyse ki, nispeten basit bir (Array.slice evrensel nesne, bir "gibi bir dizi" ile çalışır, çünkü ironik olan) bir Array içine nesne, bir "gibi bir dizi" açmak için deyim orada

(ve sonra args evrensel Function.apply kullanılabilecek kullanılabilir.)

+0

, askerin istediği gibi görünmüyor. – mauris

+5

Bence bu * tam olarak * askerin ne istediği. – bcat

+0

Teşekkürler, pst. Bağladığınız doküman mükemmel. Senin ya da Lauri'nin cevabını kabul edilen cevap olarak işaretlemek arasında parçalanmıştım çünkü onu orijinal soruma uygulamak için zaman ayırdı. Bir bozuk para attı. Umarım anlarsın. –

5

ben "uygulamak" ve "argümanlar" burada kullanabileceğiniz iki JavaScript kavramlardır düşünüyorum:

function fireStartedEvent() { 
    for (var i = 0; i < startedListeners.length; i++) { 
    startedListeners[i].apply(startedListeners[i], arguments); 
    } 
} 

İşte bu denedik benim Kundakçı konsolundan bazı kod:

a = function(foo) { alert('a: ' + foo); }; 
b = function(foo, bar) { alert('b: ' + foo + ', ' + bar); }; 

startedListeners = [a, b]; 

function fireStartedEvent() { 
    for (var i = 0; i < startedListeners.length; i++) { 
    startedListeners[i].apply(startedListeners[i], arguments); 
    } 
} 


fireStartedEvent('one', 'two'); 
+0

Bu kod doğru değil. argümanlar dizi gibidir. Bu "bir dizi" değil. Uygula, bir dizi ikinci parametre olarak alır. –

+0

pst, benim için işe yarayacak gibi görünüyor, çünkü uygulama (null, arguments) kullanılarak çağrılan yöntem çağrılıyor ve tüm farklı argümanları tanımak gibi görünüyor. Kaybettiğim bir sorun mu var? –

+0

@pst - Bunu bilmiyordum - Gönderdiğim fonksiyonun çalışmadığı bir örneğiniz var mı? –