jarandaf jarandaf - 3 months ago 9
Javascript Question

Using arrow functions with d3

Is it possible? I am not sure, since d3 makes heavy use of

this
rebindings and this seems to conflict with ES6 spec.

For instance, the following works fine:

// Working fine
var data = [1,2,3]
var svg = d3.select('body').append('svg').attr('height', 500).attr('width', 500).style('background-color', 'orange');
var gs = svg.selectAll('g').data(data).enter();
gs.append('circle')
.attr('cx', function () { return Math.random()*500; })
.attr('cy', function () { return Math.random()*500; })
.attr('r', function () { return Math.random()*100; })
.each(function () { console.log(this); }); // this is bound to the current element in the enter selection


While the following does not work as expected (
this
is not bound to the current element in the enter selection but to
Window
object):

var data = [1,2,3]
var svg = d3.select('body').append('svg').attr('height', 500).attr('width', 500).style('background-color', 'blue');
var gs = svg.selectAll('g').data(data).enter();
gs.append('circle')
.attr('cx', () => Math.random()*500)
.attr('cy', () => Math.random()*500)
.attr('r', () => Math.random()*100)
.each(() => console.log(this)); // this is bound to Window object


Related fiddle here.

Answer

You can use arrow functions if you don't need access to this of the current element.

Fallback to the old style functions for cases where you want to access this of the current element.

Or use explicit binding to allow your function (not arrow function) to access whatever object you want using .bind()

To avoid working with this you have the option of using d3 name or class selectors to conveniently access any element. e.g.:

var stuffINeed = svg.selectAll('.someClass');
Comments