Ich weiß, dass dies wahrscheinlich schmerzhaft einfach ist, aber es fällt mir schwer, meinen Kopf darum zu wickeln.
class Main
{
constructor()
{
requestAnimationFrame(this.update); //fine
}
update(): void
{
requestAnimationFrame(this.update); //error, because this is window
}
}
Es scheint der Fall zu sein, dass ich einen Proxy benötige, also verwenden wir Jquery
class Main
{
constructor()
{
this.updateProxy = $.proxy(this.update, this);
requestAnimationFrame(this.updateProxy); //fine
}
updateProxy: () => void
update(): void
{
requestAnimationFrame(this.updateProxy); //fine
}
}
Ich komme jedoch aus Actionscript 3 und bin mir nicht sicher, was hier passiert. Entschuldigung, ich bin nicht sicher, wo Javascript beginnt und TypeScript endet.
updateProxy: () => void
Und ich bin auch nicht davon überzeugt, dass ich das richtig mache. Das Letzte, was ich möchte, ist, dass der größte Teil meiner Klasse eine aa () -Funktion hat, auf die zugegriffen werden muss, aProxy()
da ich das Gefühl habe, zweimal dasselbe zu schreiben? Es ist normal?
jquery
this
typescript
proxy-classes
Clark
quelle
quelle
Antworten:
Wenn Sie
this
die TypeScript-Methode erfassen möchten , erfolgt dies über Pfeilfunktionen. Um Anders zu zitieren:Hier ist die Art und Weise, wie ich dies zu meinem Vorteil nutzen möchte:
class test{ // Use arrow functions func1=(arg:string)=>{ return arg+" yeah" + this.prop; } func2=(arg:number)=>{ return arg+10 + this.prop; } // some property on this prop = 10; }
Zeigen Sie dies auf dem TypeScript-Spielplatz an
Sie können sehen, dass im generierten JavaScript außerhalb des Funktionsaufrufs
this
erfasst wird :var _this = this; this.prop = 10; this.func1 = function (arg) { return arg + " yeah" + _this.prop; };
Daher wird der
this
Wert innerhalb des Funktionsaufrufs (der sein könntewindow
) nicht verwendet.Weitere Informationen : „
this
In TypeScript verstehen “ (4:05) - YouTubequelle
var _this = this;
Sie auswählenES5
; da ES2015 - Innenfunktionen -this
anstelle von_this
Wenn Sie Ihre Methoden so schreiben, wird "dies" so behandelt, wie Sie es erwarten.
class Main { constructor() { requestAnimationFrame(() => this.update()); } update(): void { requestAnimationFrame(() => this.update()); } }
Eine andere Möglichkeit wäre, 'this' an den Funktionsaufruf zu binden:
class Main { constructor() { requestAnimationFrame(this.update.bind(this)); } update(): void { requestAnimationFrame(this.update.bind(this)); } }
quelle
Siehe Seite 72 der Typenskript-Sprachspezifikation https://github.com/Microsoft/TypeScript/blob/master/doc/TypeScript%20Language%20Specification.pdf?raw=true
Pfeilfunktionsausdrücke
Im Beispiel
class Messenger { message = "Hello World"; start() { setTimeout(() => alert(this.message), 3000); } }; var messenger = new Messenger(); messenger.start();
Dies ist das tatsächlich generierte Javascript:
class Messenger { message = "Hello World"; start() { var _this = this; setTimeout(function() { alert(_this.message); }, 3000); } };
quelle
Das Problem tritt auf, wenn Sie eine Funktion als Rückruf übergeben. Bis der Rückruf ausgeführt wurde, könnte sich der Wert von "this" in das Fenster, das Steuerelement, das den Rückruf aufruft, oder etwas anderes geändert haben.
Stellen Sie sicher, dass Sie an der Stelle, an der Sie einen Verweis auf die zurückzurufende Funktion übergeben, immer einen Lambda-Ausdruck verwenden. Zum Beispiel
public addFile(file) { this.files.push(file); } //Not like this someObject.doSomething(addFile); //but instead, like this someObject.doSomething( (file) => addFile(file) );
Dies kompiliert zu so etwas wie
this.addFile(file) { this.files.push(file); } var _this = this; someObject.doSomething(_this.addFile);
Da die Funktion addFile für eine bestimmte Objektreferenz (_this) aufgerufen wird, wird nicht das "this" des Aufrufers verwendet, sondern der Wert von _this.
quelle
Kurz gesagt, das Schlüsselwort this hat immer einen Verweis auf das Objekt, das die Funktion aufgerufen hat.
Da Funktionen in Javascript nur Variablen sind, können Sie sie weitergeben.
Beispiel:
var x = { localvar: 5, test: function(){ alert(this.localvar); } }; x.test() // outputs 5 var y; y.somemethod = x.test; // assign the function test from x to the 'property' somemethod on y y.test(); // outputs undefined, this now points to y and y has no localvar y.localvar = "super dooper string"; y.test(); // outputs super dooper string
Wenn Sie mit jQuery Folgendes tun:
$.proxy(this.update, this);
Was Sie tun, ist, diesen Kontext zu überschreiben. Hinter den Kulissen wird Ihnen jQuery Folgendes empfehlen:
$.proxy = function(fnc, scope){ return function(){ return fnc.apply(scope); // apply is a method on a function that calls that function with a given this value } };
quelle
Sehr spät zur Party, aber ich denke, es ist sehr wichtig, dass zukünftige Besucher dieser Frage Folgendes berücksichtigen:
Die anderen Antworten, einschließlich der akzeptierten, verfehlen einen entscheidenden Punkt:
und
myFunction = () => { ... }
sind nicht dasselbe "mit der Ausnahme, dass letztere erfasst
this
".Die erste Syntax erstellt eine Methode für den Prototyp, während die zweite Syntax eine Eigenschaft für das Objekt erstellt, dessen Wert eine Funktion ist (die auch erfasst wird
this
). Sie können dies deutlich im transpilierten JavaScript sehen.Vollständig sein:
myFunction = function() { ... }
wäre das gleiche wie die zweite Syntax, aber ohne die Erfassung.
Die Verwendung der Pfeilsyntax behebt in den meisten Fällen das Problem der Bindung an das Objekt. Es ist jedoch nicht dasselbe, und es gibt viele Situationen, in denen Sie anstelle einer Eigenschaft eine ordnungsgemäße Funktion für den Prototyp wünschen.
In diesen Fällen einen Proxy verwenden oder
.bind()
tatsächlich ist die richtige Lösung. (Obwohl unter Lesbarkeit leiden.)Lesen Sie hier mehr (nicht in erster Linie über TypeScript, aber die Prinzipien stehen):
https://medium.com/@charpeni/arrow-functions-in-class-properties-might-not-be-as-great-as-we-think-3b3551c440b1
https://ponyfoo.com/articles/binding-methods-to-class-instance-objects
quelle
Wie wäre es so? Deklarieren Sie eine globale Variable vom Typ "myClass" und initialisieren Sie sie im Konstruktor der Klasse:
var _self: myClass; class myClass { classScopeVar: string = "hello"; constructor() { _self = this; } alerter() { setTimeout(function () { alert(_self.classScopeVar) }, 500); } } var classInstance = new myClass(); classInstance.alerter();
Hinweis: Es ist wichtig, "Selbst" NICHT als spezielle Bedeutung zu verwenden.
quelle