Most of functions in D3.js accept an anonymous function as an argument. The common examples are .attr
, .style
, .text
, .on
and .data
, but the list is way bigger than that.
In such cases, the anonymous function is evaluated for each selected element, in order, being passed:
d
)i
)nodes
)this
as the current DOM element.The datum, the index and the current group are passed as arguments, the famous first, second and third argument in D3.js (whose parameters are traditionally named d
, i
and p
in D3 v3.x). For using this
, however, one doesn’t need to use any argument:
.on("mouseover", function(){
d3.select(this);
});
The above code will select this
when the mouse is over the element. Check it working in this fiddle: https://jsfiddle.net/y5fwgopx/
As a new ES6 syntax, an arrow function has a shorter syntax when compared to function expression. However, for a D3 programmer who uses this
constantly, there is a pitfall: an arrow function doesn’t create its own this
context. That means that, in an arrow function, this
has its original meaning from the enclosing context.
This can be useful in several circumstances, but it is a problem for a coder accustomed to use this
in D3. For instance, using the same example in the fiddle above, this will not work:
.on("mouseover", ()=>{
d3.select(this);
});
If you doubt it, here is the fiddle: https://jsfiddle.net/tfxLsv9u/
Well, that’s not a big problem: one can simply use a regular, old fashioned function expression when needed. But what if you want to write all your code using arrow functions? Is it possible to have a code with arrow functions and still properly use this
in D3?
The answer is yes, because this
is the same of nodes[i]
. The hint is actually present all over the D3 API, when it describes this:
...with
this
as the current DOM element (nodes[i]
)
The explanation is simple: since nodes
is the current group of elements in the DOM and i
is the index of each element, nodes[i]
refer to the current DOM element itself. That is, this
.
Therefore, one can use:
.on("mouseover", (d, i, nodes) => {
d3.select(nodes[i]);
});
And here is the corresponding fiddle: https://jsfiddle.net/2p2ux38s/