史蒂文·艾克曼(Steven Ickman)的解决方案很方便,但并不完整。Danny Becket和Sam的答案更短,更手动,并且在具有同时需要动态范围和词法范围“ this”的回调的相同一般情况下失败。如果下面的解释是TL; DR,请跳到我的代码。
我需要保留“ this”以用于动态范围,以便与库回调一起使用,并且我需要对类实例使用词法作用域使用“ this”。我认为将实例传递给回调生成器是最优雅的做法,可以有效地让参数封闭类实例。编译器会告诉您是否错过了。我习惯于将词法范围参数称为“ outerThis”,但是“ self”或其他名称可能更好。
“ this”关键字的使用是从OO世界窃取的,当TypeScript采用它时(我假设是ECMAScript 6规范),只要方法由另一个实体调用,它们就会将词法范围的概念和动态范围的概念混为一谈。 。我对此感到有些沮丧。我希望在TypeScript中使用“ self”关键字,以便可以将词法范围的对象实例移交给它。或者,可以将JS重新定义为在需要时需要一个明确的第一位置“调用方”参数(从而一举打破所有网页)。
这是我的解决方案(从大类中删除)。特别要注意方法的调用方式,尤其是“ 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;
}
}
}