2012-06-04 2 views
2

Я изо всех сил пытаюсь понять, как работает этот код JavaScript. Я изучаю JS и не подвергаюсь динамическому функциональному языку раньше. Таким образом, я визуализую вызовы функций в процедуре бит, иерархическом порядке. С d3.js, можно сделать SVG элементы, как описано hereЦепочка функций


var dataset = [ 5, 10, 15, 20, 25 ]; 

d3.select("body").selectAll("p") 
    .data(dataset) 
    .enter() 
    .append("p") 
    .text("New paragraph!"); 

Давайте изменим последнюю строку:

.text(function(d) { return d; }); 

Проверьте, что новый код делает на этой демонстрационной странице.

Whoa! Мы использовали наши данные для заполнения содержимого каждого абзаца, благодаря магии метода data(). Вы видите, что при объединении методов в любое время после вызова данных() вы можете создать анонимную функцию, которая принимает d как вход. Метод magical data() гарантирует, что d устанавливается в соответствующее значение в вашем исходном наборе данных, учитывая текущий элемент.


Эта магия, упомянутая выше, является тем, что я не понимаю. «d» не является глобальной переменной, так как если я перехожу на другое (c) имя, оно все равно работает. Таким образом, метод data может устанавливать значение для анонимного fn.

Но, как правило, (с моим ограниченным чтением) цепочка возможна, потому что текущая функция возвращает объект, на который может быть вызван следующий метод. В приведенном выше случае метод data знает, передается ли текст («Новый абзац!») Пользователем, иначе передайте данные анонимному fn. У сомнений есть метод text вниз по линии, и data() уже выполнен. Как данные передаются анонимной функции?

спасибо.

ответ

3

Копаем в d3.JS internals показывает следующий результат для text функции:

d3_selectionPrototype.text = function(value) { 
    return arguments.length < 1 
     ? this.node().textContent : this.each(typeof value === "function" 
     ? function() { var v = value.apply(this, arguments); this.textContent = v == null ? "" : v; } : value == null 
     ? function() { this.textContent = ""; } 
     : function() { this.textContent = value; }); 
}; 

В случае, если предоставленный аргумент является функцией, следующий код запускается на выполнение:

this.each(function() { 
    var v = value.apply(this, arguments); // executing function provided 
    this.textContent = v == null ? "" : v; 
}); 

Функция each объявлена ​​как:

d3_selectionPrototype.each = function(callback) { 
    for (var j = -1, m = this.length; ++j < m;) { 
    for (var group = this[j], i = -1, n = group.length; ++i < n;) { 
     var node = group[i]; 
     if (node) callback.call(node, node.__data__, i, j); // this is the line you are interested in 
    } 
    } 
    return this; 
}; 

поэтому при каждом вызове он поставляет элемент от this. И, доходя до этого, this заселен data вызов функции.

+0

вы пригвоздили его. Большое спасибо. функция данных сохраняет отдельные значения в __data__ https://github.com/mbostock/d3/wiki/Selections#wiki-data. Один быстрый qn, хотя анонимный fn принимает только один аргумент, и через вызов он обеспечивает 4. Как это работает? – bsr

+2

Вы говорите о 'callback.call (node, node .__ data__, i, j)', правильно? Первым аргументом является область - 'this' внутри обратного вызова, затем идут данные, вы имеете в виду ее как' d', а затем - индексы. Для javascript не имеет значения, сколько именных аргументов вы используете - вы можете указать любое количество аргументов функции. Все аргументы доступны с использованием переменной 'arguments'. Именованные аргументы - это просто ярлык. Btw, заменить 'function (d) {return d; } 'с' function (d, i, j) {return d; } 'и проверьте это сами. – Li0liQ

+0

еще раз за вашу помощь! – bsr

0

Ну, я никогда раньше не использовал d3, но это то, что я понимаю.

d является объектом данных (я бы назвал его data вместо d был установлен в методе data().

Так что же метод text() делает? Будет ли она будет вызывать функцию и использовать его выход, что-то вроде это:.

function text (callback) { 
    var theText; 
    if (typeof callback === "function") { 
    theText = callback(dataset); 
    } else { 
    theText = callback; 
    } 
    // does something more 
} 

Таким образом, если обратный вызов является вызов функции, и использовать возвращаемое значение как текст

Затем, что я угадал, заключается в том, что если функция является массивом, она будет вызывать текстовый метод для каждого элемента массива.

Что-то вроде этого ...

function text(callback) { 
    var theText; 
    if (typeof callback === "function") { 
    theText = callback(dataset); 
    } else { 
    theText = callback; 
    } 
    if (theText instanceof Array) { // this is not the best way to check if an object is an array, I'll come back to this later. I'm sorry. 
    for (var i=0, len=theText.length; i<len; i++) { 
     text(theText[i]); 
    } 
    } else { 
    // do something else 
    } 
    // do something more 
} 

пожалуйста, примите во внимание, что это будет очень простой вариант того, что на самом деле происходит.

Если это не ясно, пожалуйста, дайте мне знать.

Смежные вопросы