D3 javascript foreach和每个之间的区别


Answers:


177

首先,.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(...))。从技术上讲,您可以调用.forEach()d3选择,因为在后台,d3选择是具有附加功能的数组(其中一个是.each())。但是您不应该这样做,因为:

  1. 这样做将不会产生所需的行为。知道如何.forEach()与d3选择配合使用以产生任何所需的行为,需要深入了解d3的内部工作原理。那么,如果您只能使用API​​记录的公开部分,为什么要这样做。

  2. 当您调用.each(function(d, i) { })d3选择时,您不仅获得了d而且i:,该函数被调用,使得该this函数内任何位置的关键字都指向与关联的HTML DOM元素d。换句话说,console.log(this)从内部function(d,i) {}将记录类似<div class="foo"></div>或类似的html元素。这很有用,因为然后您可以在此this对象上调用function ,以更改其CSS属性,内容或其他内容。通常,您可以使用d3设置这些属性,如中所示d3.select(this).style('color', '#c33');

主要的外卖是,使用.each()您可以访问三件事情你需要:dthisi。使用.forEach(),在数组上(例如从一开始的示例中),您只会得到2件事(di),并且您必须做一堆工作才能将HTML元素与这2件事相关联。尤其是d3的用途。


16
感谢您写了一个不错的答案,并且没有包含任何在SO上如此普遍的不必要的蛇纹……
凯文·H·林

1
这里应该有一个警告:当您确实需要为'this'关键字设置不同的作用域,但是在您的调用函数中不需要基准时,selection [0] .forEach(...)比selection。更加方便。如果“ this”在仅引用DOM元素之外有意义,则需要在父函数中使用“ self = this”解决方法。
sdupton 2015年

this在许多d3场景中,@ sdupton作用域设置是一个问题,在这些场景中您传递了更高阶的函数,例如selection.style("color", function(d,i) { /* here 'this' is a DOM element */ })。我认为,这就是为什么d3类(例如d3.svg.axis,例如)不使用prototype定义类的方法的部分原因,这是避免依赖的一种方法this。但是我看不出如何selection[0].forEach(...)避免这个问题。是不是同样的问题?
metamit

1
@meetamit您可以使用第二个参数显式定义“ this”的范围,以便在Array.prototype.forEach中使用,该参数在每个元素上调用的函数之后传递。当您编写类似于面向对象包装器的任何东西(我正在使用ES6类)时,丢失对“ this”的明确作用域可能会令人um目结舌。
sdupton

2
@sdupton,很酷-我不知道.forEach接受第二个参数来进行范围界定this。它让我意识到,您可以使用类似ish的东西,.each()通过使用javascript来与d3达到相同的效果.bind()方法。例如,以下内容将适用thiswindowconsole.log并将其记录下来:selection.each(function() { console.log(this); }.bind(window))
Meetamit 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.