Рішення Стівена Ікмана зручне, але неповне. Відповіді Денні Бекета та Сема коротші та більш ручні, і вони не вдаються в тому самому загальному випадку, коли є зворотний виклик, який потребує як динамічного, так і лексичного охоплення "цього" одночасно. Перейти до мого коду, якщо моє пояснення нижче TL; DR ...
Мені потрібно зберегти "this" для динамічного масштабування для використання із зворотними викликами бібліотеки, і мені потрібно мати "this" з лексичним масштабуванням до екземпляра класу. Я стверджую, що найелегантніше передавати екземпляр у генератор зворотних викликів, фактично дозволяючи закрити параметр над екземпляром класу. Компілятор повідомляє, якщо ви пропустили це. Я використовую домовленість про виклик лексично визначеного параметра "externalThis", але "self" або інше ім'я може бути кращим.
Використання ключового слова "this" викрадено з світу OO, і коли TypeScript прийняв його (із 6 специфікацій ECMAScript, я припускаю), вони поєднали поняття з лексичним масштабом та поняття з динамічним масштабом, коли метод викликається іншим суб'єктом . Я трохи збентежений цим; Я віддав би перевагу ключовому слову "self" у TypeScript, щоб я міг видалити екземпляр об'єкта з лексичним масштабом. Крім того, 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;
}
}
}