Jaka jest różnica między forEach
iw each
D3js?
Odpowiedzi:
Po pierwsze, .forEach()
nie jest częścią d3, jest to natywna funkcja tablic javascript. Więc,
["a", "b", "c"].forEach(function(d, i) { console.log(d + " " + i); });
// Outputs:
a 0
b 1
c 2
I to działa nawet jeśli d3 nie jest załadowany na stronie.
Następnie d3 .each()
działa na selekcjach d3 (co otrzymujesz, gdy ty d3.selectAll(...)
). Technicznie rzecz biorąc, możesz wywołać .forEach()
selekcję d3, ponieważ za kulisami selekcja d3 to tablica z dodatkowymi funkcjami (jedną z nich jest .each()
). Ale nie powinieneś tego robić, ponieważ:
Nie spowoduje to pożądanego zachowania. Wiedza o tym, jak używać .forEach()
selekcji d3 w celu wywołania dowolnego pożądanego zachowania, wymagałaby dogłębnego zrozumienia wewnętrznego działania d3. Po co więc to robić, jeśli możesz po prostu skorzystać z udokumentowanej, publicznej części interfejsu API.
Kiedy wywołujesz .each(function(d, i) { })
selekcję d3, otrzymujesz coś więcej niż tylko d
i i
: funkcja jest wywoływana w taki sposób, że this
słowo kluczowe w dowolnym miejscu wewnątrz tej funkcji wskazuje na powiązany element HTML DOM d
. Innymi słowy, console.log(this)
od wewnątrz function(d,i) {}
zarejestruje coś takiego <div class="foo"></div>
lub jakikolwiek inny element html. Jest to przydatne, ponieważ wtedy możesz wywołać funkcję na tym this
obiekcie, aby zmienić jego właściwości CSS, zawartość lub cokolwiek innego. Zwykle używasz d3 do ustawiania tych właściwości, jak w d3.select(this).style('color', '#c33');
.
Głównym wynos jest to, że za pomocą .each()
można uzyskać dostęp do 3 rzeczy, które trzeba: d
, this
i i
. W .forEach()
przypadku tablicy (jak w przykładzie od początku) otrzymujesz tylko 2 rzeczy ( d
i i
), i będziesz musiał wykonać sporo pracy, aby również powiązać element HTML z tymi 2 rzeczami. I to między innymi jest przydatne w d3.
this
jest problemem w wielu scenariuszach d3, w których przekazujesz funkcje wyższego rzędu, w tym na przykład selection.style("color", function(d,i) { /* here 'this' is a DOM element */ })
. Uważam, że po części dlatego klasy d3 (jak d3.svg.axis
na przykład) nie używają prototype
metod definiowania klas - jako sposobu na uniknięcie polegania na this
. Ale nie widzę, jak selection[0].forEach(...)
uniknąć tego problemu. Czy to nie ten sam problem?
.forEach
zaakceptowałem drugi parametr do określania zakresu this
. Uświadomiłem sobie, że możesz użyć czegoś podobnego do osiągnięcia tego samego efektu z d3, .each()
używając .bind()
metody javascript . Na przykład, następujący zakres wola this
, aby window
i będzie go console.log: selection.each(function() { console.log(this); }.bind(window))
.