В чем разница между forEach
и each
в D3js?
источник
В чем разница между 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))
.