我正在努力了解此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; });


在此演示页面上查看新代码的作用。

哇!借助data()方法的神奇之处,我们使用数据填充了每个段落的内容。您可以看到,将方法链接在一起时,在调用data()之后的任何时间,您都可以创建一个接受d作为输入的匿名函数。神奇的data()方法可确保将d设置为原始数据集中相应的值(给定当前元素)。



上面提到的这种魔力是我无法理解的。 “ d”不是全局变量,就像我更改为另一个(c)名称一样,它仍然有效。因此,data方法可能正在设置匿名fn的值。

但是,通常(在有限的阅读范围内)可以进行链接,因为当前函数返回一个对象,可以在其上调用下一个方法。在上述情况下,data方法如何知道用户是否传递了文本(“ New段落!”),否则将数据传递给匿名fn。令人怀疑的是,text方法是线下的,并且data()已经执行。数据如何传递给匿名函数?

谢谢。

最佳答案

深入研究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中的一个元素。并且,深入到此,thisdata函数调用填充。

09-17 11:32
查看更多