Wie übergebe ich diesen Kontext an eine Funktion?


213

Ich dachte, das wäre etwas, das ich leicht googeln könnte, aber vielleicht stelle ich nicht die richtige Frage ...

Wie stelle ich ein, worauf sich "dies" in einer bestimmten Javascript-Funktion bezieht?

Zum Beispiel wie bei den meisten Funktionen von jQuery wie:

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

Wie schreibe / rufe ich meine eigenen Standalone-Funktionen auf, die beim Aufruf eine entsprechende "this" -Referenz haben? Ich verwende jQuery. Wenn es also eine jQuery-spezifische Methode gibt, wäre dies ideal.



Ich weiß, dass dies eine alte Frage ist, aber für andere, die hier landen, siehe jQuery$.proxy
RyBolt

Antworten:


302

Mit Javascripts .call()und .apply()Methoden können Sie den Kontext für eine Funktion festlegen .

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

var obj_a = {
    name:  "FOO"
};

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

Jetzt können Sie anrufen:

myfunc.call(obj_a);

Welches würde alarmieren FOO. Umgekehrt obj_bwürde das Vorbeigehen alarmieren BAR!!. Der Unterschied zwischen .call()und .apply()besteht darin, dass .call()eine durch Kommas getrennte Liste verwendet wird, wenn Sie Argumente an Ihre Funktion übergeben und .apply()ein Array benötigen.

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

Daher können Sie hookmit der apply()Methode einfach eine Funktion schreiben . Zum Beispiel möchten wir der jQuerys- .css()Methode ein Feature hinzufügen . Wir können die ursprüngliche Funktionsreferenz speichern, die Funktion mit benutzerdefiniertem Code überschreiben und die gespeicherte Funktion aufrufen.

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

Da das magische argumentsObjekt ein Array-ähnliches Objekt ist, können wir es einfach an übergeben apply(). Auf diese Weise garantieren wir, dass alle Parameter an die ursprüngliche Funktion übergeben werden.


4
Nur ein kleiner Leckerbissen: Wenn Sie die Funktion beispielsweise wiederholt aufrufen müssen obj_a, können Sie beispielsweise eine Kopie davon erstellen var boud_myfunc = myfunc.bind(obj_a)und bound_myfunc()bei Bedarf einfach aufrufen .
Badart

44

Verwendungfunction.call :

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

Wo thatist das Objekt, das Sie thisin der Funktion haben möchten ?


1
functionist ein reserviertes Schlüsselwort; Erwägen Sie, Ihre Antwort so zu aktualisieren, dass sie eine benannte Funktion enthält, da function.call(...)JavaScript nicht gültig ist.
Daniel Allen

1
@DanielAllen: Ohne die Definition des Beispielfunktionsnamens, den ich angeben würde, wird der Code immer noch einen JS-Fehler auslösen. Ich habe jedoch den Namen der Beispielfunktion aktualisiert.
Palswim

16

jQuery verwendet eine .call(...)Methode, um den aktuellen Knoten thisinnerhalb der Funktion zuzuweisen, die Sie als Parameter übergeben.

BEARBEITEN:

Haben Sie keine Angst, im Zweifelsfall in den Code von jQuery zu schauen. Alles ist in klarem und gut dokumentiertem Javascript.

dh: Die Antwort auf diese Frage ist um Zeile 574,
callback.call( object[ name ], name, object[ name ] ) === false


12

Sie können die Verwendung bind Funktion den Kontext setzen thisinnerhalb einer Funktion.

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

12

Ein weiteres grundlegendes Beispiel:

Funktioniert nicht:

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

Arbeiten:

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

Also im Grunde: Fügen Sie einfach .bind (this) zu Ihrer Funktion hinzu


Dies sollte die akzeptierte Antwort sein. Viel einfachere Syntax, viel einfacher im Kopf ... gute Arbeit Joery
nenea
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.