I am trying to create a "generic" class for a D3 force graph.
When the graphTick()
function is called (or any other method it seems...) the member values of the class are undefined
as if the method was not bound to that instance.
I wonder if I'm misunderstanding the JS way of writing a class (I'm from a C++ background) or if I'm misusing the D3 framework. Maybe both?
I've tried to replace....
simulation.on("tick", this.graphTick)
...by:
simulation.on("tick", function(){
/*graphTick implementation*/
})
But then it looked like it was called by some anomymous object from D3, so I'm thinking my problem is probably more about JS syntax.
Got a Codepen setup with this class and a quick test: https://codepen.io/mrelemental/pen/VGLNLa
You're using a JavaScript class, which is quite uncommon in D3 codes. There is no problem in using classes per se, but you have to take extra care when dealing with the this
keyword.
The issue in your code is the value of this
inside the graphTick
function: in the "tick"
listener, this
is the simulation itself. According to the API:
When a specified event is dispatched, each listener will be invoked with the
this
context as the simulation.
You can easily see it by yourself if you do a console.log(this)
inside the function. You'll get:
{tick: function, restart: function, stop: function, nodes: function, etc...}
And that explains why both your attempts didn't work: in both of them, this
is the simulation itself.
The solution is simple, just pass the correct this
to the graphTick
function:
simulation.on("tick", this.graphTick.bind(this))
Here you can find more information about bind()
: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind
And here is the updated code: https://codepen.io/anon/pen/qgpxNX?editors=0010