【发布时间】:2012-11-08 01:59:27
【问题描述】:
D3js 中forEach 和each 有什么区别?
【问题讨论】:
标签: javascript d3.js
D3js 中forEach 和each 有什么区别?
【问题讨论】:
标签: javascript d3.js
首先,.forEach() 不是 d3 的一部分,它是 javascript 数组的原生函数。所以,
["a", "b", "c"].forEach(function(d, i) { console.log(d + " " + i); });
// Outputs:
a 0
b 1
c 2
即使页面上没有加载 d3,它也可以工作。
接下来,d3 的.each() 适用于 d3 选择(当您使用d3.selectAll(...) 时会得到什么)。从技术上讲,您可以在 d3 选择上调用 .forEach(),因为在幕后,d3 选择是一个具有额外功能的数组(其中一个是 .each())。但你不应该这样做,因为:
这样做不会产生所需的行为。要知道如何将.forEach() 与 d3 选择一起使用以产生任何所需的行为,需要深入了解 d3 的内部工作原理。那么为什么要这样做,如果您可以使用 API 的文档化、公开部分。
d 关联的元素。换句话说,来自function(d,i) {} 内部的console.log(this) 将记录类似<div class="foo"></div> 或任何html 元素的内容。这很有用,因为你可以在这个this 对象上调用函数来更改它的CSS 属性、内容或其他任何东西。通常,您使用 d3 来设置这些属性,如 d3.select(this).style('color', '#c33');。
主要的收获是,使用.each(),您可以访问您需要的3 个东西:d、this 和i。使用.forEach(),在一个数组上(就像一开始的例子一样)你只能得到两件事(d 和i),你必须做很多工作才能将 HTML 元素与这两件事。这就是 d3 的用处。
【讨论】:
this 的作用域是许多 d3 场景中的一个问题,在这些场景中,您传递高阶函数,包括例如 selection.style("color", function(d,i) { /* here 'this' is a DOM element */ })。我相信这就是为什么 d3 类(例如 d3.svg.axis)不使用 prototype 定义类的方法的部分原因——作为避免依赖 this 的一种方式。但我看不出selection[0].forEach(...) 是如何避免这个问题的。是不是同样的问题?
.forEach 接受了第二个参数来确定this 的范围。它让我意识到你可以使用类似的东西来实现与 d3 的 .each() 相同的效果,方法是使用 javascript 的 .bind() 方法。例如,以下内容将this 限定为window 并将console.log 它:selection.each(function() { console.log(this); }.bind(window))。