Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Map function in D3, confused about multiple functions passed in

This example from Mike Bostock:

https://bl.ocks.org/mbostock/34f08d5e11952a80609169b7917d4172

The following line confuses me and i was wondering if someone could clear it up.

x.domain(s.map(x2.invert, x2));

Why is x2 being passed in as a second argument? As far as I know the second parameter is the optional thisArg argument, but as invert doesn't need it why's it being passed in? The code seems to work fine without it so what am I missing?

like image 407
Mike Mellor Avatar asked May 23 '17 12:05

Mike Mellor


2 Answers

This question can finally be settled as Mike Bostock thankfully reacted to GitHub issue #173 Simplify / clarify rescaleX and rescaleY.:

The answer is: it’s good practice in JavaScript. If the object’s methods happen to be bound to the object, it’s unnecessary to specify this, but one generally shouldn’t assume so unless it is documented (and not likely to change in a future version).

like image 81
altocumulus Avatar answered Oct 17 '22 02:10

altocumulus


(edit: well, my supposition ended up being wrong, see the other answer)


Two years after this very interesting question was posted I had a glimpse of the probable solution to this mystery. However, a good deal of supposition remains: only Mike Bostock, the author of that code, has the real answer (provided that he still remembers why he did it that way).

As OP mentioned, this thisArg in the map function is irrelevant:

x.domain(s.map(x2.invert, x2));
//this bit here -----------^

That's because the invert method of the scale needs no this value.

However, if we look some dozen lines further down at that same code, we'll find this:

context.select(".brush").call(brush.move, x.range().map(t.invertX, t));

And here we find thisArg again:

x.range().map(t.invertX, t)
//thisArg ---------------^

The reason for this, if we look at the source code for invertX, is that invertX needs a value to use as this:

invertX: function(x) {
    return (x - this.x) / this.k;
}

And here comes my supposition: invert and invertX are quite similar names and, even despite Bostock had invented them and had written countless D3 codes, he confused the two and set the thisArg for x2.invert, which although being unnecessary didn't break the code, and went unnoticed by the author.

One extra argument in favour of this supposition is that, in both cases, he used the object as the thisArg. Compare:

x2.invert, x2
|          |
t.invertX, t
like image 36
6 revs, 2 users 99% Avatar answered Oct 17 '22 02:10

6 revs, 2 users 99%