Soluție Steven Ickman este la îndemână, dar incomplet. Danny Becket și răspunsurile lui Sam sunt mai scurte și mai manuale, și nu în același caz general, de a avea un apel invers, care are nevoie atât de dinamic și lexical scoped „acest lucru“, în același timp. Treci la codul meu, dacă explicația mea de mai jos este TL; DR ...
Trebuie să păstreze „acest“ pentru definire a domeniului dinamic pentru utilizarea cu callback bibliotecă, și am nevoie pentru a avea un „acest“ cu definire a domeniului lexicală la instanța de clasă. Eu susțin că este cel mai elegant de a trece instanța într - un generator de apel invers, lăsând în mod eficient închiderea parametrul peste instanță de clasă. Compilatorul va spune dacă ai pierdut acest lucru. Eu folosesc o convenție de asteptare lexical Scoped parametru „outerThis“, ci „ de sine“ , sau un alt nume ar putea fi mai bine.
Utilizarea „acest“ cuvânt cheie este furat din lumea OO, iar când typescript a adoptat (de la ECMAScript 6 specificatii presupun), au contopit un concept lexical scoped și un concept scoped dinamic, ori de câte ori o metodă este numită de către o altă entitate . Sunt puțin bosumflat la acest lucru; Aș prefera o „sine“ cuvânt cheie dactilografiat, astfel încât să pot mână instanța de obiect lexical scoped de pe ea. Alternativ, JS ar putea fi redefinit pentru a solicita o primă poziție parametru explicit „apelant“, atunci când este nevoie (și, prin urmare, rupe toate paginile web într-o singură lovitură).
Iată soluția mea (excizat dintr-o clasă mare). Ia un gânsac, în special, la modul în care sunt numite metode, iar corpul „dragmoveLambda“, în special:
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;
}
}
}