-->

Explain Mike Bostock Node-Parsing Loop [duplicate]

2019-02-25 03:38发布

问题:

This question already has an answer here:

  • variable declaration conditional syntax 3 answers

I'm relatively new to JavaScript and d3, but I'm really interested in force-directed layouts. In Mike Bostock's force-directed visualizations, he tends to parse nodes from a list of links using the following code (or similar):

var links = [
    {source: "A", target: "B"},
    {source: "B", target: "C"},
    {source: "C", target: "A"}];

var nodes = {};

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});
});

I completely understand what he ultimately accomplishing here, I just want to understand the JavaScript syntax in the forEach loop better (actually, at all). If someone could explain, I'd really appreciate it.

It's obviously very elegant code, but I can't find an explanation anywhere on the internet - I'm probably missing a key term in my searches, so I'm reluctantly asking the question here. What is really throwing me off:

  • What the two assignments on either side of the || do ,
  • The order of the first assignment of each line (left-hand side of each ||): why is it link.source = nodes[link.source] not nodes[link.source] = link.source, for instance.

回答1:

In the code below

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

It means

link.source = nodes[link.source]

if nodes[link.source] is not undefined.

If nodes[link.source] is undefined then block below will get executed.

(nodes[link.source] = {name: link.source})//assigning new value to nodes[link.source]

and the above value will be set to link.source

So if you make it simple it would be like:

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

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

Hope this helps!

Explanation for your comment

Question (a = b || c equates to a = b but if b is undefined make a = c, right?)

YES

Question What still doesn't make sense is why the left side of these assignments are link.source and link.target?Those are already defined, they're what we want to populate nodes with?

Yes! you are correct here Those are already defined. link.source is currently = "A" After the block executes each link.source will be pointing to an object, something like this. link.source = {name:A}

Let me know if you still have confusion.