Bu bağlamı bir işleve nasıl aktarabilirim?


213

Bunun kolayca google yapabileceğim bir şey olacağını düşündüm, ama belki de doğru soruyu sormuyorum ...

Belirli bir javascript işlevinde "bu" neyin ifade ettiğini nasıl ayarlayabilirim?

örneğin, jQuery gibi birçok işlev gibi:

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

Çağrıldığında uygun bir "bu" referansa sahip kendi bağımsız işlevlerimi nasıl yazabilir / arayabilirim? JQuery kullanıyorum, bu yüzden jQuery'ye özgü bir yol varsa, bu ideal olurdu.



Bu eski bir soru olduğunu biliyorum, ama buraya iniş diğerleri için bkz. JQuery$.proxy
RyBolt

Yanıtlar:


303

Javascripts .call()ve .apply()yöntemler bir işlevin bağlamını ayarlamanıza olanak tanır .

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

var obj_a = {
    name:  "FOO"
};

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

Şimdi arayabilirsiniz:

myfunc.call(obj_a);

Hangi uyarır FOO. Diğer yoldan, geçiş obj_buyanık olurdu BAR!!. Arasındaki fark .call()ve .apply()olmasıdır .call()size işleve argümanlar geçiriyorsanız eğer virgülle ayrılmış listesi alır ve .apply()bir dizi ihtiyacı var.

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

Bu nedenle, yöntemi hookkullanarak kolayca bir işlev yazabilirsiniz apply(). Örneğin, jQuerys .css()yöntemine bir özellik eklemek istiyoruz . Orijinal işlev referansını saklayabilir, özel kod ile işlevin üzerine yazabilir ve saklanan işlevi çağırabiliriz.

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

Sihirli argumentsnesne bir nesne gibi bir dizi olduğundan, onu aktarabiliriz apply(). Bu şekilde, tüm parametrelerin orijinal fonksiyona aktarıldığını garanti ederiz.


4
Sadece eğlenceli bir tidbit: obj_aÖrneğin referans olarak işlevi tekrar tekrar çağırmanız gerekiyorsa , bunun bir kopyasını oluşturabilir var boud_myfunc = myfunc.bind(obj_a)ve bound_myfunc()gerektiğinde arayabilirsiniz .
wbadart

44

Kullanımfunction.call :

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

İşlevde thatolmasını istediğiniz nesne nerede this.


1
functionayrılmış bir anahtar kelimedir; yanıtınızı, function.call(...)geçerli bir JavaScript olmadığı için adlandırılmış bir işlev içerecek şekilde güncelleyin .
Daniel Allen

1
@DanielAllen: Sağlayacağım örnek işlev adının tanımı olmadan, kod yine de bir JS hatası atar. Ancak, örnek işlev adını güncelledim.
palswim

16

jQuery .call(...), geçerli düğümü thisparametre olarak ilettiğiniz işlevin içine atamak için bir yöntem kullanır .

DÜZENLE:

Bir şüphe duyduğunuzda jQuery kodunun içine bakmaktan korkmayın, hepsi açık ve iyi belgelenmiş Javascripttir.

yani: bu sorunun cevabı 574. satır civarındadır,
callback.call( object[ name ], name, object[ name ] ) === false


12

Bir işlevin içeriğini ayarlamak için bind işlevini kullanabilirsiniz this.

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

12

Başka bir temel örnek:

Çalışmıyor:

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

Çalışma:

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

Temel olarak: işlevinize sadece .bind (this) ekleyin


Bu kabul edilen cevap olmalı. Çok daha kolay sözdizimi, akılda çok daha kolay ... iyi iş Joery
nenea
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.