katzkode
katzkode

Reputation: 2001

Multiple Assignments in JavaScript Expression and Syntax Explanation

The following code is from Mike Bostock's Force-Directed Graph with Mouseover. I am sorry that I can't ask a more pointed question about this code, but I was wondering if someone could explain the syntax in the forEach block that computes the distinct nodes from the links.

What exactly is happening in the line below and what is being assigned to what variables? Is there a name for performing multiple assignments in the same expression?

link.source = nodes[link.source] || (nodes[link.source] = {name: link.source});

var links = [
  {source: "Ericsson", target: "ZTE", type: "suit"},
  {source: "Kodak", target: "Samsung", type: "resolved"},
  {source: "Apple", target: "Samsung", type: "suit"},
  {source: "Kodak", target: "RIM", type: "suit"},
  {source: "Nokia", target: "Qualcomm", type: "suit"}
];

var nodes = {};

// Compute the distinct nodes from the links.
links.forEach(function(link) {
  link.source = nodes[link.source] || (nodes[link.source] = {name: link.source});
  link.target = nodes[link.target] || (nodes[link.target] = {name: link.target});
});

Upvotes: 1

Views: 48

Answers (1)

musicnothing
musicnothing

Reputation: 3985

There's actually a fair amount to unpack in this line:

link.source = nodes[link.source] || (nodes[link.source] = {name: link.source});

First it should be mentioned that x = y || z is equivalent* to this:

if (y)
    x = y;
else
    x = z;

It should also be noted that i = (j = k) means that we're going to assign k to j, and then assign that value to i as well. So in the end, i, j, and k will all have the same value.

So in this case, we're really getting this:

if (nodes[link.source]) {
    link.source = nodes[link.source];
} else {
    nodes[link.source] = { name: link.source };
    link.source = nodes[link.source];
}

That is, if nodes[link.source] is truthy (not 0, null, undefined, empty string), then link.source will be assigned nodes[link.source] as a value.

If it is falsy, then both link.source AND nodes[link.source] will be assigned {name: link.source} as their value.


*Those are equivalent because when you're evaluating an ||, if the left hand side is truthy, there is no need to evaluate the right hand side--you can already evaluate the statement as true. So in JavaScript, it "returns" y if y is truthy, z if y is falsy but z is truthy, or false if both are falsy.

Upvotes: 2

Related Questions