Решение Стивена Ickman является удобным, но неполным. Дэнни Бекет и ответы Сэма короче и более ручные, и не в том же самом общем случае наличия обратного вызова, которая нуждается как динамичное и лексический контекстное «это» в то же самое время. Перейти к моему коду, если мое объяснение ниже TL; DR ...
Мне нужно сохранить «это» для динамического определения объема для использования с библиотекой обратных вызовов, и мне нужно иметь «это» с лексической областью видимости для экземпляра класса. Я считаю , что это самый элегантный передать экземпляр в генератор обратного вызова, эффективно позволяя закрыть параметр над экземпляром класса. Компилятор говорит вам , если вы пропустили это делать. Я использую условность вызова лексический контекстный параметр «outerThis», а «я» или другое название может быть лучше.
Использование «это» ключевое слова украдено из OO мира, и когда машинопись приняла его (из ECMAScript 6 спецификации я полагаю), они сплавлены с лексический контекстной концепцией и динамически контекстной концепция, всякий раз, когда метод вызывается другим объект , Я немного обижен на это; Я предпочел бы «само» ключевое слово в машинописном, так что я могу передать экземпляр лексический контекстный объект отходящему от него. С другой стороны, JS может быть пересмотрена, чтобы требовать явного первого-позиционный параметр «вызывающего абонента», когда это необходимо (и, таким образом, разорвать все веб-страницы в одном махом).
Вот мое решение (вырезано из большого класса). Взглянуть в частности, на то, как называются методы, и тело «dragmoveLambda», в частности:
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;
}
}
}