it-swarm.com.de

var self = das?

Durch die Verwendung von Instanzmethoden als Rückrufe für Ereignishandler wird der Gültigkeitsbereich von this von "Meine Instanz" in "Was auch immer gerade als Rückruf bezeichnet wurde" geändert. Mein Code sieht also so aus

function MyObject() {
  this.doSomething = function() {
    ...
  }

  var self = this
  $('#foobar').bind('click', function(){
    self.doSomethng()
    // this.doSomething() would not work here
  })
}

Es funktioniert, aber ist das der beste Weg, es zu tun? Es sieht seltsam aus für mich.

180
defnull

Diese Frage ist nicht spezifisch für jQuery, sondern spezifisch für JavaScript im Allgemeinen. Das Kernproblem besteht darin, wie eine Variable in eingebetteten Funktionen "kanalisiert" wird. Dies ist das Beispiel:

var abc = 1; // we want to use this variable in embedded functions

function xyz(){
  console.log(abc); // it is available here!
  function qwe(){
    console.log(abc); // it is available here too!
  }
  ...
};

Diese Technik beruht auf der Verwendung eines Verschlusses. Es funktioniert jedoch nicht mit this, da this eine Pseudovariable ist, die sich dynamisch von Bereich zu Bereich ändern kann:

// we want to use "this" variable in embedded functions

function xyz(){
  // "this" is different here!
  console.log(this); // not what we wanted!
  function qwe(){
    // "this" is different here too!
    console.log(this); // not what we wanted!
  }
  ...
};

Was können wir tun? Weisen Sie es einer Variablen zu und verwenden Sie es über den Alias:

var abc = this; // we want to use this variable in embedded functions

function xyz(){
  // "this" is different here! --- but we don't care!
  console.log(abc); // now it is the right object!
  function qwe(){
    // "this" is different here too! --- but we don't care!
    console.log(abc); // it is the right object here too!
  }
  ...
};

this ist in dieser Hinsicht nicht eindeutig: arguments ist die andere Pseudovariable, die auf die gleiche Weise behandelt werden sollte - durch Aliasing.

205
Eugene Lazutkin

Ja, das scheint ein allgemeiner Standard zu sein. Einige Programmierer benutzen sich selbst, andere benutzen mich. Es wird als Referenz auf das "echte" Objekt im Gegensatz zum Ereignis verwendet.

Es hat eine Weile gedauert, bis ich richtig weiterkam, es sieht auf den ersten Blick merkwürdig aus.

Normalerweise mache ich das ganz oben auf meinem Objekt (entschuldigen Sie meinen Demo-Code - er ist konzeptioneller als alles andere und keine Lektion in exzellenter Codiertechnik):

function MyObject(){
  var me = this;

  //Events
  Click = onClick; //Allows user to override onClick event with their own

  //Event Handlers
  onClick = function(args){
    me.MyProperty = args; //Reference me, referencing this refers to onClick
    ...
    //Do other stuff
  }
}
17
BenAlabaster

Wenn Sie ES2015 ausführen oder Script und ES5 ausführen, können Sie Pfeilfunktionen in Ihrem Code verwenden. Dieser Fehler tritt nicht auf, und dies bezieht sich auf den gewünschten Bereich in Ihrer Instanz.

this.name = 'test'
myObject.doSomething(data => {
  console.log(this.name)  // this should print out 'test'
});
12
Aran Dekar
var functionX = function() {
  var self = this;
  var functionY = function(y) {
    // If we call "this" in here, we get a reference to functionY,
    // but if we call "self" (defined earlier), we get a reference to function X.
  }
}

bearbeiten: Trotz verschachtelter Funktionen innerhalb eines Objekts wird das globale Fensterobjekt und nicht das umgebende Objekt übernommen.

10
serkan

Eine Lösung besteht darin, Ihren gesamten Rückruf mit der JavaScript-Methode bind an Ihr Objekt zu binden.

Sie können dies mit einer benannten Methode tun,

function MyNamedMethod() {
  // You can now call methods on "this" here 
}

doCallBack(MyNamedMethod.bind(this)); 

Oder mit einem anonymen Rückruf

doCallBack(function () {
  // You can now call methods on "this" here
}.bind(this));

Wenn Sie diese Schritte ausführen, anstatt auf var self = this Zuzugreifen, werden Sie verstehen, wie sich die Bindung von this in Javascript verhält und nicht auf eine Abschlussreferenz angewiesen ist.

Der Operator für fette Pfeile in ES6 ist im Grunde dasselbe wie der Aufruf von .bind(this) für eine anonyme Funktion:

doCallback( () => {
  // You can reference "this" here now
});
4
Bart Dorsey

Ich habe jQuery nicht verwendet, aber in einer Bibliothek wie Prototype können Sie Funktionen an einen bestimmten Bereich binden. In diesem Sinne würde Ihr Code folgendermaßen aussehen:

 $('#foobar').ready('click', this.doSomething.bind(this));

Die bind-Methode gibt eine neue Funktion zurück, die die ursprüngliche Methode mit dem von Ihnen angegebenen Bereich aufruft.

3
neonski

Fügen Sie einfach hinzu, dass Sie dies in ES6 aufgrund von Pfeilfunktionen nicht tun müssen, da sie den Wert this erfassen.

2
aug

Ich denke, es hängt tatsächlich davon ab, was Sie in Ihrer doSomething -Funktion tun werden. Wenn Sie mit diesem Schlüsselwort auf MyObject -Eigenschaften zugreifen möchten, müssen Sie das verwenden. Aber ich denke, dass das folgende Codefragment auch funktioniert, wenn Sie keine besonderen Dinge mit object(MyObject) -Eigenschaften tun.

function doSomething(){
  .........
}

$("#foobar").ready('click', function(){

});
1
Milinda