Because when you write this:
force = d3.layout.force()
.size([width, height])
.nodes(dataNodes)
.links(dataLinks);
You're doing what is called a method chaining. d3.js
is known to use them a lot and each method chaining (with this framework at least) returns
an object, depending of the method
you call. With this particular code, it acts this way:
- Set the size of the
force
object and return
the force
object
- Set the
nodes
of the force
object and return
the nodes
property of force
- Set the
links
of the nodes
object, and return
the links
property of nodes
So, each method chaining that you add returns something different. At the end of all the method calls, the whole thing will be considered as returning the return
value of your last call, and it will assign it to the variable at the left of the =
operator. Here, your force
variable.
It's exactly as if you wrote:
force = d3.layout.force()
force = force.size([width, height])
force = force.nodes(dataNodes)
force = force.links(dataLinks)
When, later on, you iterate
over your force
variable, you necessarily iterate over the links
array, because that's what you assigned to force
.
Tip 1: The tricky part is that here, and generally in d3.js
, each method does not return
the same objects. Both d3.layout.force()
and size()
return the actual force
object, whereas nodes()
returns the nodes
object and links()
returns the links
object. It's cascading method chaining. Each element of the chain is called on the object returned by the previous method call.
Tip 2: you can understand from this that it's not necessarily the best fit to name this variable force
.
There's also a cool explanation that goes into further details from Scott Murray.