D3 javascript Difference between foreach and each
Solution 1:
First, .forEach()
is not part of d3, it's a native function of javascript arrays. So,
["a", "b", "c"].forEach(function(d, i) { console.log(d + " " + i); });
// Outputs:
a 0
b 1
c 2
And that works even if d3 is not loaded on the page.
Next, d3's .each()
works on d3 selections (what you get when you d3.selectAll(...)
). Technically, you can call .forEach()
on a d3 selection, since behind the scenes, a d3 selection is an array with extra functions (one of them is .each()
). But you shouldn't do that because:
Doing so will not produce the desired behavior. Knowing how to use
.forEach()
with a d3 selection in order to produce any desired behavior would require intimate understanding of the inner workings of d3. So why do it, if you can just use the documented, public part of the API.When you call
.each(function(d, i) { })
on a d3 selection, you get more than justd
andi
: the function gets invoked such that thethis
keyword anywhere inside that function points to the HTML DOM element associated withd
. In other wordsconsole.log(this)
from insidefunction(d,i) {}
will log something like<div class="foo"></div>
or whatever html element it is. And that's useful, because then you can call function on thisthis
object in order change its CSS properties, contents or whatever. Usually, you use d3 to set these properties, as ind3.select(this).style('color', '#c33');
.
The main takeaway is that, using .each()
you get access to 3 things you need: d
, this
and i
. With .forEach()
, on an array (like in the example from the beginning) you only get 2 things (d
and i
), and you'd have to do a bunch of work to also associate an HTML element with those 2 things. And that, among other things, is how d3 is useful.