2014-07-24 3 views
2

Я смотрел некоторый большой d3.js code examples, когда я увидел что-то вроде:декларация переменной условный синтаксис

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

я не получил сразу, как в настоящее время объявлена ​​вар узлы.

Моя первая догадка, чтобы перевести его в:

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

Но ссылки не рисуются больше.

В чем разница между двумя методами?

В чем смысл исходного синтаксиса, это просто ярлык или увеличение его производительности?

Есть ли наилучшая практика в таких случаях?

Редактировать

Так что, если я стараюсь, чтобы полностью понять

link.source = nodes[link.source] || (nodes[link.source] = {name: link.source}); 
  1. As узлов [link.source] является объектом link.source берет свою ссылку. Это всегда происходит.

  2. ИЛИ состояние, я не уверен, чтобы получить эту часть.

    Я думаю, если узлы [link.source] определяется link.source = узлы [link.source] возвращающие нам не нужно идти дальше.

    Если она не определена и возвращать ложь, положение силы или идти дальше ...

  3. узлы [link.source] получает значение так благодаря ссылке link.source наведен к тому же значению.

    Думаю, на этом этапе link.source пока не содержащей ссылку на узлов [link.source], но его первоначальное значение. Он будет содержать новую ссылку после запятой.

Я что-то не так? Пункт 2 мне кажется странным.

ответ

2

Код, используемый в примере, представляет собой просто синтаксический ярлык. Это эквивалентно

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

Все это необходимо, поскольку узлы только неявно объявляются через ссылки - то есть, нет ни в одном списке узлов, он собирается только путем обхода ссылок и «сбор» источников и целей. Это то, что хранится в nodes - это сопоставление от идентификатора узла (от ссылок) к объекту, представляющему узел.

Приведенный выше код одновременно заполняет эту карту, создавая новые объекты для невидимых узлов (т. Е. Те, которые отсутствуют в отображении) и вставляют соответствующее сопоставление. Источники и цели ссылок затем обновляются, чтобы указывать на те объекты (которые позже будут управляться компоновкой силы для установки своих позиций) вместо идентификатора узла, как указано в исходных данных.

Редактировать: Ваши измененные интерпретации верны. Это в основном то, что происходит.

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

Может быть переведены:

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

(То же самое с link.target).

Итак:

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

будет преобразован в:

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

и узлы будут равны:

nodes = { 
    "test1": { name: "test1" }, 
    "test2": { name: "test2" }, 
    "test3": { name: "test3" }, 
    "test4": { name: "test4" }, 
} 
+0

Внешняя проверка 'если (link.source! = Узлы [link.source]) {' это на самом деле не нужно в этом случае (и не присутствуют в исходном коде). –

+0

Это неявное ('link.source' должно быть равно« узлам [link.source] 'в конце) и будет препятствовать установке' link.source = nodes [link.source]; 'более одного раза для повторяющихся значений , – manji

+0

Это карта - не знаете, как вы получите дубликаты ценностей? И нет, это не подразумевается. Исходный код мог бы выполнять несколько присвоений, если бы были дубликаты значений. –

0

мое понимание к

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

есть, если nodes[link.source] не существует

тогда вобще link.source = nodes[link.source] = {name: link.source};