Steven Ickman Lösung ist praktisch, aber unvollständig. Danny Becket und Sams Antworten sind kürzer und manuelle, und nicht in dem gleichen allgemeinen Fall einen Rückruf aufweist, die sowohl dynamische als auch lexikalische „diese“ zur gleichen Zeit benötigt. Weiter zu meinen Code, wenn meine Erklärung unten ist TL; DR ...
Ich brauche „diese“ für dynamischen Scoping für die Verwendung mit Bibliothek Rückrufen zu bewahren, und ich brauche ein „this“ mit lexikalischem Scoping auf die Klasseninstanz haben. Ich behaupte , dass es eleganteste ist die Instanz in einen Callback - Generator passieren, effektiv den Parameter Schließung über die Klasseninstanz im Stich gelassen. Der Compiler sagt Ihnen , wenn Sie dies tun verpassten. Ich benutze eine Konvention , die lexikalische Parameter „outerThis“ nennen, sondern „Selbst“ oder ein anderer Name könnte besser sein.
Die Verwendung des „this“ Schlüsselwort aus der OO-Welt gestohlen, und als Typoskript es angenommen (von ECMAScript 6 Spezifikationen nehme ich an), sie verschmelzt ein lexikalisches Konzept und ein dynamisch scoped Konzept, wann immer eine Methode, mit einer anderen Einheit aufgerufen wird . Ich bin ein wenig an diesem verstimmt; Ich würde ein „Selbst“ Schlüsselwort in Typoskript bevorzugen, so dass ich die lexikalischen Objektinstanz aus der es von Hand kann. Alternativ könnte JS neu definiert werden, um einen expliziten erste Position „Anrufer“ Parameter erforderlich ist, wenn es benötigt wird (und damit alle Web-Seiten auf einem Schlag brechen).
Hier ist meine Lösung (aus einer großen Klasse ausgeschnitten). Nehmen Sie einen Blick insbesondere auf die Art und Weise der Verfahren genannt werden, und um den Körper von „dragmoveLambda“ insbesondere:
export class OntologyMappingOverview {
initGraph(){
...
// Using D3, have to provide a container of mouse-drag behavior functions
// to a force layout graph
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;
// Referring to "this" in dynamic scoping context
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;
// *Call* these callback Lambda methods rather than passing directly to the callback caller.
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;
}
}
}