Lewati fungsi JavaScript sebagai parameter

665

Bagaimana cara melewati fungsi sebagai parameter tanpa fungsi yang mengeksekusi di fungsi "induk" atau menggunakan eval()? (Karena saya sudah membaca bahwa itu tidak aman.)

Aku punya ini:

addContact(entityId, refreshContactList());

Ini berhasil, tetapi masalahnya adalah itu refreshContactList api ketika fungsi dipanggil, bukan ketika itu digunakan dalam fungsi.

Saya bisa mengatasinya dengan menggunakan eval(), tetapi itu bukan praktik terbaik, menurut apa yang saya baca. Bagaimana saya bisa melewatkan fungsi sebagai parameter dalam JavaScript?

imperium2335
sumber

Jawaban:

930

Anda hanya perlu menghapus tanda kurung:

addContact(entityId, refreshContactList);

Ini kemudian melewati fungsi tanpa menjalankannya terlebih dahulu.

Berikut ini sebuah contoh:

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

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

addContact(1, refreshContactList);
Fenton
sumber
6
@stevefenton, pertimbangkan untuk memperbarui jawaban Anda dengan komentar h2ooooooo, itu akan sangat berguna.
Morgan Wilde
5
Berdasarkan pertanyaan, callback tidak menerima parameter, itulah sebabnya saya tidak menyertakannya. Saya akan menambahkan komentar tentang itu.
Fenton
4
@ Veverke Akan terlihat seperti ini ...addContact(1, function(id) { console.log(id); });
Fenton
4
@Steve Fenton: setelah membaca balasan Anda, saya bertanya pada diri sendiri mengapa saya bertanya ... :-)
Veverke
1
Sintaks kelas di ECMAScript tidak akan memiliki =tanda ... class myFuncs {daripada class myFuncs = {. Anda juga harus menjalankan dalam lingkungan yang mendukung sintaksis kelas (belum semua browser mendukungnya). Jika Anda masih berjuang, mungkin lebih cocok untuk pertanyaan yang sama sekali baru karena masalah Anda bukan tentang fungsi lulus - itu adalah sintaks ES umum.
Fenton
338

Jika Anda ingin melewatkan fungsi, cukup rujuk dengan nama tanpa tanda kurung:

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

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

Tetapi kadang-kadang Anda mungkin ingin melewatkan fungsi dengan argumen yang disertakan , tetapi tidak memanggilnya sampai panggilan balik dipanggil. Untuk melakukan ini, saat memanggilnya, cukup bungkus dalam fungsi anonim, seperti ini:

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

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

Jika Anda suka, Anda juga bisa menggunakan fungsi terapkan dan memiliki parameter ketiga yang merupakan array argumen, seperti:

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"]); 
dallin
sumber
72
ini harus diberi peringkat lebih tinggi karena ia juga membahas cara menyampaikan suatu fungsi dengan argumen
deltanine
3
Dan sesuatu yang akan saya tambahkan adalah bahwa fitur ini saja - dapat melewati fungsi JavaScript sebagai argumen atau variabel atau sejenisnya - adalah fitur yang membuat JavaScript sangat kuat dan begitu hebat untuk
dikodekan
@ Compynerd255 Saya setuju, ini dan kemampuan untuk dengan cepat membuat objek literal adalah dua aspek favorit saya dari Javascript. Saya selalu kehilangan objek literal dalam bahasa yang tidak memilikinya.
dallin
3
Saya sangat berterima kasih kepada Javascript untuk menyediakan fitur ini dan kepada Anda @allin untuk memberi tahu saya bahwa itu ada.
Dipendu Paul
Untuk contoh "membungkusnya dalam fungsi anonim", jika tidak jelas, fungsi anonim mengembalikan fungsi itu sendiri (dengan parameter) dan dipanggil ketika mencapai tanda kurung di func (). Saya perlu beberapa saat untuk mencari tahu, jadi saya pikir itu mungkin membantu orang lain.
hubpixel
51

Contoh 1:

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

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

Contoh 2:

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

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

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

Lihat ini

Gadde
sumber
pada contoh pertama Anda harus menambahkan kata kunci kembali, seperti ini: function funct (a, foo) {return foo (a) // ini akan mengembalikan a} jika tidak, Anda akan tidak terdefinisi
Artem Fedotov
34

Untuk melewatkan fungsi sebagai parameter, cukup hapus tanda kurung!

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); 

Gagasan di balik ini adalah bahwa fungsi sangat mirip dengan variabel. Alih-alih menulis

function ToBeCalled() { /* something */ }

Anda mungkin juga menulis

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

Ada perbedaan kecil di antara keduanya, tapi bagaimanapun - keduanya merupakan cara yang valid untuk mendefinisikan suatu fungsi. Sekarang, jika Anda mendefinisikan suatu fungsi dan secara eksplisit menetapkannya ke suatu variabel, tampaknya cukup logis, bahwa Anda dapat meneruskannya sebagai parameter ke fungsi lain, dan Anda tidak perlu tanda kurung:

anotherFunction(ToBeCalledVariable);
kenaifan
sumber
2
Cukup typeof paramFunc == "function"sudah, karena jika tidak bisa dipanggil, maka Anda dapat mengabaikannya.
Jimmy Knoot
16

Ada ungkapan di antara programmer JavaScript: "Eval is Evil" jadi cobalah menghindarinya dengan cara apa pun!

Selain jawaban Steve Fenton, Anda juga dapat melewati fungsi secara langsung.

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

function callAddContact() {
    addContact("entity", function() { DoThis(); });
}
Matthew Layton
sumber
8

Saya memotong semua rambut saya dengan masalah itu. Saya tidak dapat membuat contoh di atas berfungsi, jadi saya berakhir seperti:

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')");

Dan itu berfungsi seperti pesona ... untuk setidaknya yang saya butuhkan. Semoga ini bisa membantu.

Fenix ​​Aoras
sumber
6

Saya menyarankan untuk meletakkan parameter dalam array, dan kemudian membaginya menggunakan .apply()fungsi. Jadi sekarang kita dapat dengan mudah melewatkan fungsi dengan banyak parameter dan menjalankannya dengan cara yang sederhana.

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
Naramsim
sumber
5

Anda juga dapat menggunakan eval()untuk melakukan hal yang sama.

//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");

Itu dia. Saya juga mencari solusi ini dan mencoba solusi yang disediakan di jawaban lain tetapi akhirnya berhasil dari contoh di atas.

NullPointer
sumber
2

Ini dia pendekatan lain:

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

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

Bahkan, sepertinya agak rumit, bukan.

dapatkan metode sebagai parameter:

 function JS_method(_callBack) { 

           _callBack("called");  

        }

Anda dapat memberikan sebagai metode parameter:

    JS_method(function (d) {
           //Finally this will work.
           alert(d)
    });
Hakki Eser
sumber
1
Tolong, jelaskan jawaban Anda.
MillaresRoo
2

Jawaban lain melakukan pekerjaan yang sangat baik untuk menggambarkan apa yang sedang terjadi, tetapi satu "gotcha" yang penting adalah memastikan bahwa apa pun yang Anda lewati memang referensi ke suatu fungsi.

Misalnya, jika Anda melewati string alih-alih fungsi, Anda akan mendapatkan kesalahan:

function function1(my_function_parameter){
    my_function_parameter();   
}

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

function1(function2); //This will work

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

Lihat JsFiddle

Pemenang
sumber
0

Suatu saat ketika Anda perlu berurusan dengan event handler sehingga perlu melewati acara juga sebagai argumen, sebagian besar perpustakaan modern suka bereaksi, sudut mungkin memerlukan ini.

Saya perlu mengganti fungsi OnSubmit (fungsi dari perpustakaan pihak ketiga) dengan beberapa validasi khusus pada reactjs dan saya melewati fungsi dan acara keduanya seperti di bawah ini

SEMULA

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

BUAT FUNGSI BARU uploaddan dipanggil lewat onSubmitdan acara sebagai argumen

<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);
}
sumit
sumber
-3

Anda dapat menggunakan JSON juga untuk menyimpan dan mengirim fungsi JS.

Periksa yang berikut ini:

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



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

Ini akan mencetak 'a'.

Berikut ini memiliki efek yang sama dengan yang di atas:

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

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

function main(){
    myFunc2(myFunc1);
}

Yang juga memiliki efek yang sama dengan yang berikut:

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


function myFunc2 (functionParameter){
    functionParameter();
}

function main(){
    myFunc2(myFunc1);
}

Dan paradigma objek menggunakan Kelas sebagai prototipe objek:

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

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


function main(){    
    var myClass = new Class();  
    myClass.myFunc2(myClass.myFunc1);
}
gazga
sumber
9
Contoh kode top Anda bukan JSON. Ini adalah Objek JavaScript standar. Anda juga tidak dapat mengirim / menerima fungsi dalam JSON.
Matthew Layton