В чем разница между forEachи eachв D3js?
Ответы:
Во-первых, .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()). Но этого делать не стоит, потому что:
Это не приведет к желаемому поведению. Знание того, как использовать .forEach()с выбором d3 для получения любого желаемого поведения, потребует глубокого понимания внутренней работы d3. Так зачем это делать, если можно просто использовать документированную общедоступную часть API.
Когда вы вызываете .each(function(d, i) { })выбор d3, вы получаете больше, чем просто dи i: функция вызывается так, что thisключевое слово в любом месте этой функции указывает на элемент HTML DOM, связанный с d. Другими словами, console.log(this)изнутри function(d,i) {}будет регистрироваться что-то вроде <div class="foo"></div>или любой другой элемент html. И это полезно, потому что тогда вы можете вызвать функцию для этого thisобъекта, чтобы изменить его свойства CSS, содержимое или что-то еще. Обычно вы используете d3 для установки этих свойств, как в d3.select(this).style('color', '#c33');.
Основная идея состоит в том, что, используя .each()вы получите доступ к 3 вещи , которые нужны: d, thisи i. С .forEach(), в массиве (как в примере с самого начала) вы получаете только 2 вещи ( 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принял 2-й параметр для определения объема this. Это заставило меня понять, что вы можете использовать что-то подобное для достижения того же эффекта с d3, .each()используя .bind()метод javascript . Например, следующая будет сфера , thisчтобы windowи console.log его: selection.each(function() { console.log(this); }.bind(window)).