简体   繁体   中英

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 .

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. eg:

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

If you are using d3v4, you can access the current DOM node like this:

gs.append('circle')
    .attr('cx', () => Math.random()*500)
    .attr('cy', () => Math.random()*500)
    .attr('r', () => Math.random()*100)
    .each((d, i, j) => console.log(j[i])); 
        // j is current group, i is current index

It is not possible to modify the behaviour of an arrow function. Their binding is 'hardcoded' and cannot be changed by re-binding with the bind method or by invoking any other Function method that accepts an explicit execution context (eg apply ). The same can be said of any bound function -- once bound, the returned function is bound forever .

Is it possible?

With the above in mind, if d3 uses bind ing to provide convenient chaining behaviour, this cannot be achieved using arrow functions until d3's API is modified in some way to accommodate them.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM