Jak przekazać ten kontekst do funkcji?

213

Myślałem, że byłoby to coś, co mógłbym łatwo znaleźć w Google, ale może nie zadaję właściwego pytania ...

Jak ustawić cokolwiek „to” odnosi się do danej funkcji javascript?

na przykład, podobnie jak w przypadku większości funkcji jQuery, takich jak:

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

Jak pisać / wywoływać własne samodzielne funkcje, które mają odpowiednie „to” odniesienie po wywołaniu? Używam jQuery, więc jeśli istnieje specyficzny dla jQuery sposób, byłoby to idealne.

użytkownik126715
źródło
Możliwy duplikat: stackoverflow.com/questions/520019/…
user123444555621
Wiem, że to stare pytanie, ale dla innych lądujących tutaj patrz jQuery$.proxy
RyBolt

Odpowiedzi:

303

JavaScript .call()i .apply()metody pozwalają ustawić kontekst dla funkcji.

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

var obj_a = {
    name:  "FOO"
};

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

Teraz możesz zadzwonić:

myfunc.call(obj_a);

Co by zaalarmowało FOO. Odwrotnie, przekazywanie obj_bbyłoby ostrzeżeniem BAR!!. Różnica między .call()i .apply()polega na tym, że .call()pobierana jest lista rozdzielona przecinkami, jeśli przekazujesz argumenty do swojej funkcji i .apply()potrzebujesz tablicy.

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

Dlatego możesz łatwo napisać funkcję hookza pomocą apply()metody. Na przykład chcemy dodać funkcję do .css()metody jQuerys . Możemy zapisać oryginalne odwołanie do funkcji, zastąpić funkcję niestandardowym kodem i wywołać zapisaną funkcję.

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

Ponieważ magiczny argumentsobiekt jest obiektem podobnym do tablicy, możemy go po prostu przekazać apply(). W ten sposób gwarantujemy, że wszystkie parametry zostaną przekazane do oryginalnej funkcji.

jAndy
źródło
4
Po prostu fajna ciekawostka: jeśli chcesz na przykład wywoływać tę funkcję wielokrotnie obj_a, możesz na przykład utworzyć jej kopię var boud_myfunc = myfunc.bind(obj_a)i po prostu zadzwonić bound_myfunc()w razie potrzeby.
wbadart
44

Użyjfunction.call :

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

Gdzie thatjest obiekt, który ma być thisw funkcji.

palswim
źródło
1
functionjest zastrzeżonym słowem kluczowym; rozważ zaktualizowanie swojej odpowiedzi, aby zawierała nazwaną funkcję, ponieważ function.call(...)jest to niepoprawny JavaScript.
Daniel Allen,
1
@DanielAllen: Bez definicji jakiejkolwiek przykładowej nazwy funkcji, którą podałbym, kod nadal generuje błąd JS. Ale zaktualizowałem nazwę przykładowej funkcji.
palswim
16

jQuery używa .call(...)metody do przypisania bieżącego węzła do thisfunkcji przekazywanej jako parametr.

EDYTOWAĆ:

Nie bój się zaglądać do kodu jQuery, gdy masz wątpliwości, wszystko jest w przejrzystym i dobrze udokumentowanym JavaScript.

tzn .: odpowiedź na to pytanie jest około linii 574,
callback.call( object[ name ], name, object[ name ] ) === false

Mikrofon
źródło
12

Możesz użyć funkcji powiązania, aby ustawić kontekst thisfunkcji.

function myFunc() {
  console.log(this.str)
}
const myContext = {str: "my context"}
const boundFunc = myFunc.bind(myContext);
boundFunc(); // "my context"
Scott Jungwirth
źródło
12

Kolejny podstawowy przykład:

Nie działa:

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

Pracujący:

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

Więc w zasadzie: po prostu dodaj .bind (this) do swojej funkcji

Joery
źródło
To powinna być zaakceptowana odpowiedź. Znacznie łatwiejsza składnia, dużo łatwiejsza myśl ... dobra robota Joery
nenea