D3 javascript ความแตกต่างระหว่าง foreach และ each


คำตอบ:


179

ประการแรก.forEach()ไม่ได้เป็นส่วนหนึ่งของ d3 แต่เป็นฟังก์ชันดั้งเดิมของอาร์เรย์จาวาสคริปต์ ดังนั้น,

["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วัตถุนี้เพื่อเปลี่ยนคุณสมบัติ CSS เนื้อหาหรืออะไรก็ได้ โดยปกติคุณใช้ d3 เพื่อตั้งค่าคุณสมบัติเหล่านี้เช่นเดียวกับในd3.select(this).style('color', '#c33');.

Takeaway ที่สำคัญคือว่าการใช้.each()ที่คุณได้รับการเข้าถึง 3 สิ่งที่คุณต้องการ: d, และthis iด้วย.forEach()อาร์เรย์ (เช่นในตัวอย่างตั้งแต่ต้น) คุณจะได้รับ 2 สิ่งเท่านั้น ( dและi) และคุณต้องทำงานหลายอย่างเพื่อเชื่อมโยงองค์ประกอบ HTML กับ 2 สิ่งนั้นด้วย และเหนือสิ่งอื่นใด d3 มีประโยชน์อย่างไร


17
ขอขอบคุณสำหรับการเขียนคำตอบที่ดีและสำหรับการทำมันโดยไม่รวมใด ๆ ของ Snark ที่ไม่จำเป็นที่ธรรมดาอื่น ๆ ดังนั้น ...
เควินเอชหลิน

1
ควรมีข้อแม้ที่นี่: เมื่อคุณต้องการขอบเขตที่แตกต่างกันสำหรับคีย์เวิร์ด "this" แต่คุณไม่ต้องการข้อมูลในฟังก์ชันที่เรียกว่าการเลือก [0] สำหรับแต่ละ (... ) นั้นสะดวกกว่าการเลือกมากแต่ละ ซึ่งจำเป็นต้องใช้วิธีแก้ปัญหา 'self = this' ในฟังก์ชันพาเรนต์หาก 'this' มีความหมายนอกเหนือจากการอ้างถึงองค์ประกอบ DOM เท่านั้น
sdupton

@sdupton กำหนดขอบเขตสำหรับthisเป็นความกังวลในสถานการณ์ d3 selection.style("color", function(d,i) { /* here 'this' is a DOM element */ })มากมายที่คุณผ่านในฟังก์ชั่นการสั่งซื้อที่สูงขึ้นรวมทั้งตัวอย่าง ผมเชื่อว่าเป็นบางส่วนทำไมเรียน d3 (เหมือนd3.svg.axisตัวอย่าง) ไม่ได้ใช้prototypeวิธีการของการกำหนดชั้นเรียน - thisเป็นวิธีที่จะหลีกเลี่ยงการพึ่งพา แต่ฉันไม่เห็นว่าselection[0].forEach(...)จะหลีกเลี่ยงปัญหานี้ได้อย่างไร มันไม่ใช่ปัญหาเดียวกันเหรอ?
พบกัน

1
@meetamit คุณสามารถกำหนดขอบเขต 'this' อย่างชัดเจนเพื่อใช้ใน Array.prototype.forEach ด้วยอาร์กิวเมนต์ที่สองซึ่งส่งผ่านหลังจากฟังก์ชันที่จะเรียกใช้ในแต่ละองค์ประกอบ เมื่อคุณกำลังเขียนสิ่งที่คล้ายกับกระดาษห่อหุ้มเชิงวัตถุ (ฉันใช้คลาส ES6) การสูญเสียขอบเขตที่ชัดเจนของ 'สิ่งนี้' อาจทำให้คนเกียจคร้าน
sdupton

2
@sdupton เย็น - ฉันไม่ทราบว่า.forEachได้รับการยอมรับพระรามที่ 2 thisสำหรับการกำหนดขอบเขต มันทำให้ฉันรู้ว่าคุณสามารถใช้สิ่งที่คล้ายกันเพื่อให้ได้เอฟเฟกต์เดียวกันกับ d3 .each()โดยใช้.bind()วิธีการของจาวาสคริปต์ ยกตัวอย่างเช่นขอบเขตต่อไปนี้จะthisไปwindowและจะ console.log selection.each(function() { console.log(this); }.bind(window))มัน
พบกัน
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.