Bagaimana cara meneruskan konteks ini ke suatu fungsi?

213

Saya pikir ini akan menjadi sesuatu yang bisa saya lakukan dengan mudah di google, tapi mungkin saya tidak mengajukan pertanyaan yang tepat ...

Bagaimana cara mengatur apa pun yang dimaksud "ini" dalam fungsi javascript yang diberikan?

misalnya, suka dengan sebagian besar fungsi jQuery seperti:

$(selector).each(function() {
   //$(this) gives me access to whatever selector we're on
});

Bagaimana cara saya menulis / memanggil fungsi mandiri saya sendiri yang memiliki referensi "ini" yang sesuai saat dipanggil? Saya menggunakan jQuery, jadi jika ada cara khusus jQuery untuk melakukannya, itu akan ideal.

pengguna126715
sumber
Kemungkinan rangkap: stackoverflow.com/questions/520019/...
user123444555621
Saya tahu ini adalah pertanyaan lama, tetapi untuk orang lain yang mendarat di sini, lihat jQuery$.proxy
RyBolt

Jawaban:

303

Javascript .call()dan .apply()metode memungkinkan Anda untuk mengatur konteks untuk suatu fungsi.

var myfunc = function(){
    alert(this.name);
};

var obj_a = {
    name:  "FOO"
};

var obj_b = {
    name:  "BAR!!"
};

Sekarang Anda dapat menelepon:

myfunc.call(obj_a);

Yang akan mengingatkan FOO. Sebaliknya, lewat obj_bakan waspada BAR!!. Perbedaan antara .call()dan .apply()adalah yang .call()membutuhkan daftar yang dipisahkan koma jika Anda meneruskan argumen ke fungsi Anda dan .apply()membutuhkan array.

myfunc.call(obj_a, 1, 2, 3);
myfunc.apply(obj_a, [1, 2, 3]);

Oleh karena itu, Anda dapat dengan mudah menulis fungsi hookdengan menggunakan apply()metode ini. Sebagai contoh, kami ingin menambahkan fitur ke .css()metode jQuerys . Kita dapat menyimpan referensi fungsi asli, menimpa fungsi dengan kode khusus dan memanggil fungsi yang tersimpan.

var _css = $.fn.css;
$.fn.css = function(){
   alert('hooked!');
   _css.apply(this, arguments);
};

Karena argumentsobjek ajaib adalah objek mirip array, kita bisa meneruskannya apply(). Dengan begitu kami menjamin, bahwa semua parameter dilewatkan ke fungsi asli.

jandy
sumber
4
Berita gembira yang menyenangkan: jika Anda perlu memanggil fungsi berulang kali dengan merujuk obj_a, misalnya, Anda dapat membuat salinannya dengan var boud_myfunc = myfunc.bind(obj_a)dan cukup menelepon bound_myfunc()sesuai kebutuhan.
wbadart
44

Gunakanfunction.call :

var f = function () { console.log(this); }
f.call(that, arg1, arg2, etc);

Di mana thatobjek yang Anda inginkan thisdalam fungsi menjadi.

palswim
sumber
1
functionadalah kata kunci yang dipesan; pertimbangkan untuk memperbarui respons Anda untuk menyertakan fungsi yang dinamai karena function.call(...)tidak JavaScript yang valid.
Daniel Allen
1
@DanielAllen: Tanpa definisi nama fungsi sampel apa pun yang akan saya berikan, kode masih akan membuang kesalahan JS. Tapi, saya memperbarui nama fungsi sampel.
palswim
16

jQuery menggunakan .call(...)metode untuk menetapkan node saat ini ke thisdalam fungsi yang Anda berikan sebagai parameter.

EDIT:

Jangan takut untuk melihat ke dalam kode jQuery ketika Anda ragu, semuanya dalam Javascript yang jelas dan terdokumentasi dengan baik.

yaitu: jawaban untuk pertanyaan ini adalah sekitar baris 574,
callback.call( object[ name ], name, object[ name ] ) === false

Mik
sumber
12

Anda dapat menggunakan fungsi bind untuk mengatur konteks thisdalam suatu fungsi.

function myFunc() {
  console.log(this.str)
}
const myContext = {str: "my context"}
const boundFunc = myFunc.bind(myContext);
boundFunc(); // "my context"
Scott Jungwirth
sumber
12

Contoh dasar lain:

TIDAK bekerja:

var img = new Image;
img.onload = function() {
   this.myGlobalFunction(img);
};
img.src = reader.result;

Kerja:

var img = new Image;
img.onload = function() {
   this.myGlobalFunction(img);
}.bind(this);
img.src = reader.result;

Jadi pada dasarnya: cukup tambahkan .bind (ini) ke fungsi Anda

Joery
sumber
Ini harus menjadi jawaban yang diterima. Sintaks yang jauh lebih mudah, jauh lebih mudah di pikiran ... pekerjaan yang baik Joery
nenea