Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
359 views
in Technique[技术] by (71.8m points)

javascript - variable declaration conditional syntax

I was looking some great d3.js code examples when I saw something like:

var links = [
  {source: "test1", target: "test2"},
  {source: "test1", target: "test3"},
  {source: "test2", target: "test3"},
  {source: "test3", target: "test4"}
];

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

I didn't get immediately how the var nodes was being declared.

My first guess was to translate it into:

links.forEach(function(link) {
  if(link.source != nodes[link.source]){
    nodes[link.source] = {name: link.source};
  }
  if(link.target != nodes[link.target]){
    nodes[link.target] = {name: link.target};
  }
});

But the links are not drawn anymore.

What is the difference between the two methods?

What is the point of the initial syntax, is that just a shortcut or do it increase performances?

Is there a best practice to follow in such cases ?

Edit

So if I try to fully understand

link.source = nodes[link.source] || (nodes[link.source] = {name: link.source});
  1. As nodes[link.source] is an object link.source takes its reference. This is always happening.

  2. OR condition, I'm not sure to get that part.

    I guess if nodes[link.source] is defined link.source = nodes[link.source] return true we don't need go further.

    If it's not defined and return false, the OR clause force to go further...

  3. nodes[link.source] gets a value so thanks to the reference link.source is pointing to the same value.

    I guess at this stage link.source is not yet containing a reference to nodes[link.source], but its initial value. It will contain the new reference after the comma.

Am I wrong somewhere ? Point 2 seems strange to me.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The code used in the example is simply a syntactial shortcut. It is equivalent to

links.forEach(function(link) {
  if(nodes[link.source]) { // we already know about the source of this link
    link.source = nodes[link.source];
  } else { // we haven't seen this source before, create a new node for it
    nodes[link.source] = {name: link.source};
    link.source = nodes[link.source];
  }

  if(nodes[link.target]) { // we already know about the target of this link
    link.target = nodes[link.target];
  } else { // we haven't seen this target before, create a new node for it
    nodes[link.target] = {name: link.target};
    link.target = nodes[link.target];
  }
});

All of this is necessary because the nodes are only declared implicitly through the links -- that is, there's no list of nodes, it is only assembled by traversing the links and "harvesting" the sources and targets. This is what's stored in nodes -- it's a mapping from the ID of the node (from the links) to the object representing the node.

The code above simultaneously populates this map by creating new objects for unseen nodes (i.e. ones which are not present in the mapping) and inserting the respective mapping. The sources and targets of the links are then updated to point to those objects (which will later be operated on by the force layout to set their positions) instead of the ID of the node as referenced in the original data.

Edit: Your edited interpretations are correct. This is basically what's happening.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...