Steven Ickman's oplossing is handig, maar niet volledig. Danny Becket en antwoorden Sam's zijn korter en meer handmatige en falen in dezelfde algemene geval van het hebben van een callback die zowel dynamische als lexicaal scoped "dit" op hetzelfde moment nodig heeft. Doorgaan naar mijn code als mijn uitleg hieronder is TL; DR ...
Ik moet het behoud van "dit" voor dynamische scoping voor gebruik met bibliotheek callbacks, en ik moet hebben een "dit" met lexicale scoping de klasse-instantie. Ik betoog dat het het meest elegant tot de instantie overgaan in een callback generator, effectief te laten de parameter sluiting over de klasse-instantie. De compiler vertelt u als u dat doet gemist. Ik gebruik een conventie van het aanroepen van de lexicaal scoped parameter "outerThis", maar "zelf" of een andere naam misschien beter.
Het gebruik van het "dit" keyword wordt gestolen uit de OO wereld, en wanneer typoscript heeft zij (van ECMAScript 6 specs neem ik aan), ze samengevoegd een lexicaal scoped concept en een context-afhankelijke concept, wanneer een methode wordt aangeroepen door een andere entiteit . Ik ben een beetje miffed op dit; Ik zou liever een "zelf" keyword met de schrijfmachine, zodat ik de lexicaal scoped object kan bijvoorbeeld de hand van het weg. Alternatief zou JS opnieuw worden gedefinieerd om een expliciete eerste positie parameter "beller" nodig wanneer het nodig is (en dus alle webpagina's in een klap te breken).
Hier is mijn oplossing (uitgesneden uit een grote klasse). Neem een kijkje in het bijzonder naar de manier waarop de methoden worden genoemd, en het lichaam van "dragmoveLambda" in het bijzonder:
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;
}
}
}