La solución de Steven Ickman es muy útil, pero incompleta. Danny Becket y respuestas de Sam son más cortos y más manual, y fallan en el mismo caso general de tener una devolución de llamada que necesita "este", al mismo tiempo dinámico y ámbito léxico. Saltar a mi código si mi explicación a continuación es TL; DR ...
Necesito para preservar "este" de ámbito dinámico para su uso con las devoluciones de llamada de la biblioteca, y tengo que tener un "presente" con ámbito léxico a la instancia de clase. Argumento que es más elegante para pasar la instancia en un generador de devolución de llamada, dejando que efectivamente el cierre de parámetros sobre la instancia de clase. El compilador le indica si se ha perdido hacerlo. Yo uso una convención de llamar a los parámetros "outerThis alcance léxico", pero "sí" o cualquier otro nombre podría ser mejor.
El uso de la palabra "this" es robado del mundo OO, y cuando mecanografiado lo adoptó (de ECMAScript 6 especificaciones supongo), que combinó un concepto ámbito léxico y un concepto de ámbito dinámico, cada vez que un método es llamado por una entidad diferente . Estoy un poco molesto en esto; Yo preferiría una palabra clave "sí" a máquina de escribir para que pueda entregar la instancia del objeto ámbito léxico fuera de ella. Alternativamente, JS podría redefinirse para requerir un parámetro explícito primera posición de "el que llama" cuando es necesario (y por lo tanto romper todas las páginas web de una sola vez).
Aquí está mi solución (escindido de una gran clase). Echar un vistazo en particular, por la forma en se llaman los métodos, y el cuerpo de "dragmoveLambda", en particular:
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;
}
}
}