JavaScript işlevini parametre olarak iletme


665

"Ana" işlevde yürütülmeden veya kullanmadan bir işlevi parametre olarak nasıl iletirim eval()? (Güvensiz olduğunu okuduğumdan beri.)

Bu bende var:

addContact(entityId, refreshContactList());

Çalışır, ancak sorun, refreshContactListişlevde kullanıldığında değil, işlev çağrıldığında tetiklenir.

Kullanarak dolaşabilirim eval(), ama okuduğum göre en iyi uygulama bu değil. JavaScript'te bir işlevi parametre olarak nasıl iletebilirim?

Yanıtlar:


930

Parantezi kaldırmanız yeterlidir:

addContact(entityId, refreshContactList);

Bu daha sonra işlevi yürütmeden geçer.

İşte bir örnek:

function addContact(id, refreshCallback) {
    refreshCallback();
    // You can also pass arguments if you need to
    // refreshCallback(id);
}

function refreshContactList() {
    alert('Hello World');
}

addContact(1, refreshContactList);

6
@stevefenton, cevabınızı h2ooooooo yorumu ile güncellemeyi düşünün, çok yararlı olacaktır.
Morgan Wilde

5
Soruya dayanarak, geri arama parametreleri kabul etmiyor, bu yüzden onları örnek dışında bıraktım. Bununla ilgili bir yorum ekleyeceğim.
Fenton

4
@Veverke Böyle görünecektir ...addContact(1, function(id) { console.log(id); });
Fenton

4
@Steve Fenton: Cevabınızı okuduktan sonra neden kendime sordum ... :-)
Veverke

1
ECMAScript'te sınıf sözdizimi bir olmazdı =... işareti class myFuncs {yerine class myFuncs = {. Ayrıca sınıf sözdizimini destekleyen bir ortamda da çalışmanız gerekir (henüz tüm tarayıcılar bunu desteklemez). Hala mücadele ediyorsanız, probleminiz fonksiyonları geçmekle ilgili olmadığından tamamen yeni bir soruya daha uygun olabilir - bu genel ES sözdizimidir.
Fenton

338

Bir işlevi iletmek istiyorsanız, parantez olmadan ada göre başvurmanız yeterlidir:

function foo(x) {
    alert(x);
}
function bar(func) {
    func("Hello World!");
}

//alerts "Hello World!"
bar(foo);

Ancak bazen argümanları içeren bir işlevi iletmek isteyebilirsiniz , ancak geri çağrı çağrılıncaya kadar çağrılmayabilirsiniz. Bunu yapmak için, çağırırken, anonim bir işleve sarın, örneğin:

function foo(x) {
   alert(x);
}
function bar(func) {
   func();
}

//alerts "Hello World!" (from within bar AFTER being passed)
bar(function(){ foo("Hello World!") });

İsterseniz, Apply işlevini de kullanabilir ve bağımsız değişkenlerden oluşan bir dizi olan üçüncü bir parametreye sahip olabilirsiniz, örneğin:

function eat(food1, food2)
{
    alert("I like to eat " + food1 + " and " + food2 );
}
function myFunc(callback, args)
{
    //do stuff
    //...
    //execute callback when finished
    callback.apply(this, args);
}

//alerts "I like to eat pickles and peanut butter"
myFunc(eat, ["pickles", "peanut butter"]); 

71
bu, argümanlarla bir fonksiyonun nasıl geçileceğini de ele aldığı için daha üst sıralarda yer almalıdır
deltanine

3
Ve buna ekleyeceğim bir şey, tek başına bu özelliğin - JavaScript işlevlerini argümanlar veya değişkenler veya benzeri olarak geçirebilmesinin - JavaScript'i kodlamak için çok güçlü ve harika yapan özellik olmasıdır.
TheHansinator

@ Compynerd255 Katılıyorum, bu ve hızlı bir şekilde nesne değişmezleri oluşturma yeteneği, Javascript'in en sevdiğim iki yönüdür. Onlara sahip olmayan dillerde nesne değişmezlerini her zaman özlüyorum.
22

3
Bu özelliği sağladıkları için Javascript'e ve var olduğunu bana bildirdiğiniz için @dallin'a çok minnettarım.
Dipendu Paul

"Anonim bir işleve sar" örneği için, açık değilse, anonim işlev işlevin kendisini döndürür (parametrelerle) ve func () içindeki parantezlere ulaştığında çağrılır. Anlamak biraz zaman aldı, bu yüzden başkalarına yardımcı olabileceğini düşündüm.
hubpixel

51

Örnek 1:

funct("z", function (x) { return x; });

function funct(a, foo){
    foo(a) // this will return a
}

Örnek 2:

function foodemo(value){
    return 'hello '+value;
}

function funct(a, foo){
    alert(foo(a));
}

//call funct    
funct('world!',foodemo); //=> 'hello world!'

şuna bak


ilk örnekte, bunun gibi bir dönüş anahtar kelimesi eklemelisiniz: function funct (a, foo) {return foo (a) // bu bir geri dönecektir} aksi takdirde undefined alırsınız
Artem Fedotov

34

İşlevi parametre olarak iletmek için parantezleri çıkarın!

function ToBeCalled(){
  alert("I was called");
}

function iNeedParameter( paramFunc) {
   //it is a good idea to check if the parameter is actually not null
   //and that it is a function
   if (paramFunc && (typeof paramFunc == "function")) {
      paramFunc();   
   }
}

//this calls iNeedParameter and sends the other function to it
iNeedParameter(ToBeCalled); 

Bunun arkasındaki fikir, bir fonksiyonun bir değişkene oldukça benzer olmasıdır. Yazmak yerine

function ToBeCalled() { /* something */ }

sen de yazabilirsin

var ToBeCalledVariable = function () { /* something */ }

İkisi arasında küçük farklılıklar vardır, ancak her neyse - ikisi de bir işlevi tanımlamanın geçerli yollarıdır. Şimdi, bir işlevi tanımlar ve açıkça bir değişkene atarsanız, oldukça mantıklı görünür, başka bir işleve parametre olarak iletebilirsiniz ve parantez gerekmez:

anotherFunction(ToBeCalledVariable);

2
Sadece typeof paramFunc == "function"yeter, çünkü çağrılabilir değilse, yok sayabilirsiniz.
Mart'ta Jimmy Knoot

16

JavaScript programcıları arasında bir ifade var: "Eval is Evil" bu yüzden her ne pahasına olursa olsun bundan kaçınmaya çalışın!

Steve Fenton'un cevabına ek olarak, işlevleri doğrudan da iletebilirsiniz.

function addContact(entity, refreshFn) {
    refreshFn();
}

function callAddContact() {
    addContact("entity", function() { DoThis(); });
}

8

Bu konuda tüm saçlarımı kestim. Yukarıdaki örnekleri çalıştıramadım, bu yüzden şöyle bitirdim:

function foo(blabla){
    var func = new Function(blabla);
    func();
}
// to call it, I just pass the js function I wanted as a string in the new one...
foo("alert('test')");

Ve bu bir cazibe gibi çalışıyor ... en azından ihtiyacım olan şey için. Umarım biraz yardımcı olabilir.


6

Parametreleri bir diziye koymanızı ve ardından .apply()işlevi kullanarak bölmeyi öneririm . Böylece artık bir çok parametreye sahip bir fonksiyonu kolayca geçirip basit bir şekilde yürütebiliriz.

function addContact(parameters, refreshCallback) {
    refreshCallback.apply(this, parameters);
}

function refreshContactList(int, int, string) {
    alert(int + int);
    console.log(string);
}

addContact([1,2,"str"], refreshContactList); //parameters should be putted in an array

5

eval()Aynı şeyi yapmak için de kullanabilirsiniz .

//A function to call
function needToBeCalled(p1, p2)
{
    alert(p1+"="+p2);
}

//A function where needToBeCalled passed as an argument with necessary params
//Here params is comma separated string
function callAnotherFunction(aFunction, params)
{
    eval(aFunction + "("+params+")");
}

//A function Call
callAnotherFunction("needToBeCalled", "10,20");

Bu kadar. Ayrıca bu çözümü arıyordum ve diğer cevaplarda sağlanan çözümleri denedim ama sonunda yukarıdaki örnekten işe aldım.


2

İşte başka bir yaklaşım:

function a(first,second)    
{        
return (second)(first);           
}     

a('Hello',function(e){alert(e+ ' world!');}); //=> Hello world     

2

Aslında, biraz karmaşık gibi görünüyor, değil.

parametre olarak get yöntemi:

 function JS_method(_callBack) { 

           _callBack("called");  

        }

Parametre yöntemi olarak verebilirsiniz:

    JS_method(function (d) {
           //Finally this will work.
           alert(d)
    });

1
Lütfen cevabınızı açıklayınız.
MillaresRoo

2

Diğer cevaplar neler olup bittiğini açıklayan mükemmel bir iş çıkarır, ancak önemli bir “gotcha”, geçtiğiniz her şeyin gerçekten bir işleve referans olduğundan emin olmaktır.

Örneğin, işlev yerine bir dizeden geçerseniz hata alırsınız:

function function1(my_function_parameter){
    my_function_parameter();   
}

function function2(){
 alert('Hello world');   
}

function1(function2); //This will work

function1("function2"); //This breaks!

Bkz. JsFiddle


0

Olay işleyicisiyle başa çıkmanız gerektiğinde, olayı bir argüman olarak da geçmeniz gerektiğinde, tepki, açısal gibi modern kütüphanelerin çoğunun buna ihtiyacı olabilir.

Reatjs üzerinde bazı özel doğrulama ile OnSubmit işlevini (üçüncü taraf kitaplığından işlev) geçersiz kılmalıyım ve aşağıdaki gibi işlev ve olayı geçtim

ASLINDA

    <button className="img-submit" type="button"  onClick=
 {onSubmit}>Upload Image</button>

YENİ BİR FONKSİYON YAPTI ve argüman olarak uploadgeçirilen onSubmitve olay olarak adlandırıldı

<button className="img-submit" type="button"  onClick={this.upload.bind(this,event,onSubmit)}>Upload Image</button>

upload(event,fn){
  //custom codes are done here
  fn(event);
}

-3

JS işlevlerini saklamak ve göndermek için bir JSON da kullanabilirsiniz.

Aşağıdakileri kontrol et:

var myJSON = 
{
    "myFunc1" : function (){
        alert("a");
    }, 
    "myFunc2" : function (functionParameter){
        functionParameter();
    }
}



function main(){
    myJSON.myFunc2(myJSON.myFunc1);
}

Bu 'a' yazdıracaktır.

Aşağıdakiler yukarıdakilerle aynı etkiye sahiptir:

var myFunc1 = function (){
    alert('a');
}

var myFunc2 = function (functionParameter){
    functionParameter();
}

function main(){
    myFunc2(myFunc1);
}

Hangisi aynı zamanda aşağıdakilerle aynı etkiye sahiptir:

function myFunc1(){
    alert('a');
}


function myFunc2 (functionParameter){
    functionParameter();
}

function main(){
    myFunc2(myFunc1);
}

Sınıfı nesne prototipi olarak kullanan bir nesne paradigması:

function Class(){
    this.myFunc1 =  function(msg){
        alert(msg);
    }

    this.myFunc2 = function(callBackParameter){
        callBackParameter('message');
    }
}


function main(){    
    var myClass = new Class();  
    myClass.myFunc2(myClass.myFunc1);
}

9
En iyi kod örneğiniz JSON değil. Bu standart bir JavaScript Nesnesidir. Ayrıca JSON'da işlev gönderemez / alamazsınız.
Matthew Layton
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.