0

I am encountering a strange behavior within for loop with d3.line function. This is what the loop looks like:

for (zzz = 0; zzz < 3; zzz++) {
    lines = d3.line()
        .x(function(d,i) { console.log(zzz); x([1,2,3]) })
        .y(function(d,i) { console.log(zzz); y([1,2,3]) });
}

Normally, I would expect the console.log of this to look like

0
1
2

instead I am getting

3
3
3

I spent days trying to figure out why... Can anyone help?

Here is a jfiddle. It has bare minimum in it to generate console output.

Arthur Tarasov
  • 3,517
  • 9
  • 45
  • 57

1 Answers1

1

This block:

for (zzz = 0; zzz < 3; zzz++) {
    lines = d3.line()
        .x(function(d,i) { console.log(zzz); x([1,2,3]) })
        .y(function(d,i) { console.log(zzz); y([1,2,3]) });
}

Doesn't log anything. Check this demo:

for (zzz = 0; zzz < 3; zzz++) {
  console.log("Outside d3.line, zzz is " + zzz);
  lines = d3.line()
      .x(function(d,i){console.log("Inside d3.line nothing is printed!");x([1,2,3]) })
      .y(function(d,i){console.log("Inside d3.line nothing is printed!");y([1,2,3]) });
}
<script src="https://d3js.org/d3.v4.min.js"></script>

The reason is that d3.line() is not being called (and, thus, will not print anything in the console). d3.line() is only called when you actually append the path (using lines). By that time, the for loop has finished and zzz is 3 (if you used let, it'd be 2 instead).

Also, the fact that you get 3 three times is just a coincidence, it has nothing to do with the fact that the for loop goes from 0 to 2 (looping three times), but only with the fact that you pass an array with three values to lines in your fiddle: lines([1, 2, 3]). In the following demo, it will print zzz just once for each function:

var svg = d3.select("body");
var x = d3.scaleLinear().range([0, 100]);
var y = d3.scaleLinear().range([100, 0]);

for (zzz = 0; zzz < 3; zzz++) {
  lines = d3.line()
  .x(function(d,i) { console.log("first console.log: " + zzz); x([1,2,3]) })
  .y(function(d,i) { console.log("second console.log: " + zzz); y([1,2,3]) });
}

svg.append("path").attr("d", lines([1]));
<script src="https://d3js.org/d3.v4.min.js"></script>

So, in a nutshell, you are just defining lines inside a for loop.

Gerardo Furtado
  • 100,839
  • 9
  • 121
  • 171