Die Lösung von Steven Ickman ist praktisch, aber unvollständig. Die Antworten von Danny Becket und Sam sind kürzer und manueller und scheitern im gleichen allgemeinen Fall, wenn ein Rückruf vorliegt, der gleichzeitig dynamisch und lexikalisch "dies" erfordert. Springe zu meinem Code, wenn meine Erklärung unten TL ist; DR ...
Ich muss "this" für dynamisches Scoping für die Verwendung mit Bibliotheksrückrufen beibehalten, und ich muss ein "this" mit lexikalischem Scoping für die Klasseninstanz haben. Ich behaupte, dass es am elegantesten ist, die Instanz an einen Rückrufgenerator zu übergeben und den Parameter effektiv über die Klasseninstanz schließen zu lassen. Der Compiler teilt Ihnen mit, ob Sie dies verpasst haben. Ich verwende eine Konvention zum Aufrufen des Parameters mit lexikalischem Gültigkeitsbereich "OuterThis", aber "self" oder ein anderer Name könnte besser sein.
Die Verwendung des Schlüsselworts "this" wird aus der OO-Welt gestohlen, und als TypeScript es übernahm (aus den ECMAScript 6-Spezifikationen, nehme ich an), haben sie ein Konzept mit lexikalischem Gültigkeitsbereich und ein Konzept mit dynamischem Gültigkeitsbereich zusammengeführt, wenn eine Methode von einer anderen Entität aufgerufen wird . Ich bin ein wenig verärgert darüber; Ich würde ein "self" -Schlüsselwort in TypeScript bevorzugen, damit ich die lexikalisch begrenzte Objektinstanz davon übergeben kann. Alternativ könnte JS neu definiert werden, um bei Bedarf einen expliziten "Aufrufer" -Parameter an erster Stelle zu benötigen (und somit alle Webseiten auf einen Schlag zu unterbrechen).
Hier ist meine Lösung (aus einer großen Klasse herausgeschnitten). Sehen Sie sich insbesondere die Art und Weise an, wie die Methoden aufgerufen werden, und insbesondere den Körper von "dragmoveLambda":
export class OntologyMappingOverview {
initGraph(){
...
this.nodeDragBehavior = d3.behavior.drag()
.on("dragstart", this.dragstartLambda(this))
.on("drag", this.dragmoveLambda(this))
.on("dragend", this.dragendLambda(this));
...
}
dragmoveLambda(outerThis: OntologyMappingOverview): {(d: any, i: number): void} {
console.log("redefine this for dragmove");
return function(d, i){
console.log("dragmove");
d.px += d3.event.dx;
d.py += d3.event.dy;
d.x += d3.event.dx;
d.y += d3.event.dy;
d3.select(this).attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
outerThis.vis.selectAll("line")
.filter(function(e, i){ return e.source == d || e.target == d; })
.attr("x1", function(e) { return e.source.x; })
.attr("y1", function(e) { return e.source.y; })
.attr("x2", function(e) { return e.target.x; })
.attr("y2", function(e) { return e.target.y; });
}
}
dragging: boolean =false;
dragstartLambda(outerThis: OntologyMappingOverview): {(d: any, i: number): void} {
console.log("redefine this for dragstart");
return function(d, i) {
console.log("dragstart");
outerThis.dragging = true;
outerThis.forceLayout.stop();
}
}
dragendLambda(outerThis: OntologyMappingOverview): {(d: any, i: number): void} {
console.log("redefine this for dragend");
return function(d, i) {
console.log("dragend");
outerThis.dragging = false;
d.fixed = true;
}
}
}