Pytanie D3 javascript Różnica między foreach i każdym


Jaka jest różnica pomiędzy forEach i each w D3js?


76
2017-11-20 02:36


pochodzenie




Odpowiedzi:


Pierwszy, .forEach() nie jest częścią d3, jest natywną funkcją tablic javascript. Więc,

["a", "b", "c"].forEach(function(d, i) { console.log(d + " " + i); });
// Outputs:
a 0
b 1
c 2

A to działa, nawet jeśli d3 nie jest załadowany na stronie.

Dalej, d3 .each() działa na selekcje d3 (co otrzymujesz, kiedy d3.selectAll(...)). Technicznie możesz zadzwonić .forEach() przy wyborze d3, ponieważ za kulisami, wybór d3 jest tablicą z dodatkowymi funkcjami (jednym z nich jest .each()). Ale nie powinieneś tego robić, ponieważ:

  1. Nie spowoduje to pożądanego zachowania. Wiedząc, jak korzystać .forEach() z wyborem d3 w celu wytworzenia dowolnego pożądanego zachowania wymaga intymnego zrozumienia wewnętrznego działania d3. Dlaczego tak, jeśli możesz po prostu użyć udokumentowanej, publicznej części API.

  2. Kiedy zadzwonisz .each(function(d, i) { }) przy wyborze d3 dostajesz więcej niż tylko d i i: funkcja zostanie wywołana w taki sposób, że this słowo kluczowe w dowolnym miejscu w tej funkcji wskazuje na powiązany element HTML DOM d. Innymi słowy console.log(this) ze środka function(d,i) {} Loguje coś podobnego <div class="foo"></div> lub cokolwiek innego elementu html. I to jest przydatne, ponieważ wtedy możesz wywołać funkcję na tym this obiekt w celu zmiany jego właściwości CSS, zawartości lub cokolwiek innego. Zwykle używasz d3 do ustawiania tych właściwości, jak w d3.select(this).style('color', '#c33');.

Głównym wyjściem jest to, używając .each() otrzymujesz dostęp do 3 rzeczy, które potrzebujesz: d, this i i. Z .forEach(), na tablicy (jak na przykładzie od początku) dostajesz tylko 2 rzeczy (d i i), a będziesz musiał wykonać kilka prac, aby powiązać element HTML z tymi 2 rzeczami. I to między innymi, jak użyteczny jest d3.


160
2017-11-20 04:50



Bardzo pomocne wyjaśnienie, dzięki! - Tyler Rick
Dziękuję za napisanie świetnej odpowiedzi i za to, że nie zawiera ona niepotrzebnego snarka, który jest tak powszechny w SO ... - Kevin H. Lin
Powinno tu istnieć zastrzeżenie: kiedy potrzebujesz innego zakresu dla słowa kluczowego "this", ale nie potrzebujesz bazy danych w wywołanej funkcji, wybór [0] .forEach (...) jest znacznie wygodniejszy niż wybór. co wymaga "samo = tego" obejścia w funkcji nadrzędnej, jeśli "to" ma znaczenie poza zwykłym odniesieniem do elementów DOM. - sdupton
Zakres @sdupton dla this jest problemem w wielu scenariuszach d3, w których przechodzą funkcje wyższego rzędu, na przykład na przykład selection.style("color", function(d,i) { /* here 'this' is a DOM element */ }). Uważam, że częściowo z tego powodu klasy d3 (np d3.svg.axis na przykład) nie używaj prototype metody definiowania klas - jako sposób na uniknięcie zależności this. Ale nie rozumiem jak selection[0].forEach(...) unika tego problemu. Czy to nie ten sam problem? - meetamit
@sdupton, fajnie - nie wiedziałem .forEach zaakceptował drugi parametr do wyznaczania zakresu this. Uświadomiłem sobie, że możesz użyć czegoś podobnego - to jest dla osiągnięcia tego samego efektu z d3 .each() przy użyciu javascript .bind() metoda. Na przykład następujące będą zakres this do window i konsola.loguje go: selection.each(function() { console.log(this); }.bind(window)). - meetamit