forEach
和each
在D3js中有什么区别?
首先,.forEach()
不是d3的一部分,它是JavaScript数组的本地函数。因此,
["a", "b", "c"].forEach(function(d, i) { console.log(d + " " + i); });
// Outputs:
a 0
b 1
c 2
.each()
适用于d3选择器(当您使用d3.selectAll(...)
时的内容)。从技术上讲,您可以在d3选择器上调用.forEach()
,因为在幕后,d3选择器是具有额外函数的数组之一(其中之一是.each()
)。但是您不应该这样做,因为:.forEach()
与d3选择器以产生任何所需的结果,需要深入了解d3的内部工作原理。因此,如果可以使用文档公开部分的API,为什么要这样做呢?.each(function(d, i) { })
时,不仅会得到d
和i
:该函数被调用时,this
关键字在该函数内的任何位置都指向与d
相关联的HTML DOM元素。换句话说,来自function(d,i) {}
的console.log(this)
将记录类似于<div class="foo"></div>
或其他HTML元素的内容,这很有用,因为您可以调用该函数在this
对象上更改其CSS属性、内容或其他内容。通常,您使用d3来设置这些属性,如:d3.select(this).style('color', '#c33');
。.each()
,您可以访问到需要的三个元素:d
、this
和i
。而在数组上使用.forEach()
(例如开始的示例),您只会得到两个元素(d
和i
),并且您必须执行大量的工作才能将HTML元素与这两个元素相关联。这是d3有用的方面之一。
this
进行作用域限定是一个问题,其中你会传递高阶函数,例如selection.style("color", function(d,i) { /* here 'this' is a DOM element */ })
。我认为这部分原因是 d3 类(例如d3.svg.axis
)不使用定义类的prototype
方法,以避免对this
的依赖。但我不明白selection[0].forEach(...)
如何避免这个问题。难道它不是同样的问题吗? - meetamit.forEach
接受第二个参数来限定this
的范围。这让我意识到你可以使用类似的方法通过javascript的.bind()
方法来实现d3的.each()
相同的效果。例如,以下代码将把this
限定为window
并将其打印到控制台:selection.each(function() { console.log(this); }.bind(window))
。 - meetamit