Melewati fungsi dengan parameter sebagai parameter?

151

Apakah mungkin untuk melewatkan fungsi javascript dengan parameter sebagai parameter?

Contoh:

$(edit_link).click( changeViewMode( myvar ) );
Lucia
sumber
5
Sepertinya JQuery, dan kemungkinan besar memang demikian, tetapi itu tidak relevan. Penggunaan atau parameter dan fungsinya sama, apa pun pustaka Javascript yang Anda gunakan.
Guffa
@ Guffa - Saya bertanya-tanya apakah itu harus ditandai dengan jQuery
Russ Cam
1
@Lucia Silakan pertimbangkan untuk mengubah jawaban yang diterima untuk ini .
Michał Perłakowski
Jika Anda bekerja dengan React, pertimbangkan stackoverflow.com/questions/41369497/…
Michael Freidgeim

Jawaban:

244

Gunakan "penutupan":

$(edit_link).click(function(){ return changeViewMode(myvar); });

Ini menciptakan pembungkus fungsi sementara anonim yang tahu tentang parameter dan meneruskannya ke implementasi panggilan balik yang sebenarnya.

Ferdinand Beyer
sumber
3
Jika Anda ingin memanggil suatu fungsi pada suatu objek, Anda perlu memanggil bind (). myObj.click (function () {this.doSomething ();} .bind (myObj)); Itu akan membuat "ini" menjadi myObj.
Eli
1
Bukankah ini masalah kinerja ketika berurusan dengan banyak dari ini? Misalnya, Anda membuat onPress dalam satu Baris dan Anda memiliki 10.000 baris. Ini membuat pembungkus fungsi sementara anonim baru untuk setiap Baris. Apakah ada cara lain untuk melakukannya?
Joshua Pinter
@ JoshuaPinter Teknik itu sendiri tidak menjadi masalah. Jika Anda membutuhkan panggilan fungsi yang sama 10.000 kali, Anda dapat menyimpan pembungkusnya dalam sebuah variabel, sehingga Anda membuatnya hanya sekali. Jika Anda harus melewati 10.000 konteks yang berbeda, ada sedikit yang bisa Anda lakukan. Waspadai pengoptimalan prematur: Seperti biasa dengan kinerja, Anda perlu mengukur untuk melihat apakah ada masalah atau tidak. Mesin JavaScript saat ini sangat kuat dan dapat mengoptimalkan kode dengan cara yang mengejutkan.
Ferdinand Beyer
@FerdinandBeyer Luar Biasa, terima kasih atas tipnya. Seorang teman memberi tahu saya bahwa itu adalah praktik yang buruk dan Anda sebaiknya menggunakan metode this.myFunction = this.myFunction.bind(this)Anda constructor. Tetapi, seperti yang Anda katakan, ketika Anda harus memberikan konteks berbeda untuk masing-masing, seperti semua baris yang Anda klik untuk membuka halaman detail baris itu, itu tidak dapat dihindari.
Joshua Pinter
@FerdinandBeyer, katakanlah myvar adalah string dan itu berubah antara dua doa berturut-turut melewati changeViewMode sebagai penutup, tetapi changeViewMode selalu menerima nilai pertama dari myvar, saya ingin memanggil fungsi penutupan dengan nilai argumen berbeda yang ditugaskan ke variabel myvar yang sama,
nmxprime
42

Gunakan Function.prototype.bind(). Mengutip MDN:

The bind()Metode menciptakan fungsi baru yang, saat dipanggil, memiliki nya thisset kata kunci untuk nilai disediakan, dengan urutan tertentu argumen sebelumnya yang disediakan ketika fungsi baru ini disebut.

Ini didukung oleh semua browser utama, termasuk IE9 +.

Kode Anda akan terlihat seperti ini:

$(edit_link).click(changeViewMode.bind(null, myvar));

Catatan: Saya menganggap Anda berada dalam konteks global, yaitu thisvariabelnya adalah window; jika tidak gunakan thissebagai ganti null.

Michał Perłakowski
sumber
Terima kasih, ini membantu saya. Digunakan seperti ini:$.ajax(url).done(handler.bind(this, var1, var2));
Thomas
2
Opsi mana yang terbaik? Menggunakan penutupan atau menggunakan fungsi bind? Tolong beri tahu saya jika ada dampak kinerja
Varun
5
@Varun See Mengapa mengikat lebih lambat daripada penutupan?
Michał Perłakowski
15

Tidak, tetapi Anda dapat melewatkannya tanpa parameter, dan lakukan ini:

$(edit_link).click(
  function() { changeViewMode(myvar); }
);

Jadi Anda melewati fungsi anonim tanpa parameter, fungsi itu lalu memanggil fungsi parameter Anda dengan variabel dalam penutupan

Clyde
sumber
8

Ya seperti ini:

$(edit_link).click(function() { changeViewMode(myvar) });
Philippe Leybaert
sumber
7

Atau jika Anda menggunakan es6, Anda harus dapat menggunakan fungsi panah

$(edit_link).click(() => changeViewMode(myvar));
Christian Bartram
sumber
2

Kamu bisa melakukan ini

var message  = 'Hello World';

var callback = function(){
alert(this)
}.bind(message);

lalu

function activate(callback){
  callback && callback();
}

activate(callback);

Atau jika panggilan balik Anda mengandung logika yang lebih fleksibel, Anda dapat melewati objek.

Demo

Alexandr Sargsyan
sumber
2

Ini adalah contoh mengikuti pendekatan Ferdinand Beyer:

function function1()
{
    function2(function () { function3("parameter value"); });
}
function function2(functionToBindOnClick)
{
    $(".myButton").click(functionToBindOnClick);
}
function function3(message) { alert(message); }

Dalam contoh ini "nilai parameter" dilewatkan dari function1 ke function3 melalui function2 menggunakan pembungkus fungsi.

erionpc
sumber