JavaScript: ความแตกต่างระหว่าง. forEach () และ. map ()


116

ฉันรู้ว่ามีหัวข้อแบบนี้มากมาย และฉันรู้พื้นฐาน: .forEach()ทำงานบนอาร์เรย์เดิมและอาร์เรย์.map()ใหม่

ในกรณีของฉัน:

function practice (i){
    return i+1;
};

var a = [ -1, 0, 1, 2, 3, 4, 5 ];
var b = [ 0 ];
var c = [ 0 ];
console.log(a);
b = a.forEach(practice);
console.log("=====");
console.log(a);
console.log(b);
c = a.map(practice);
console.log("=====");
console.log(a);
console.log(c);

และนี่คือผลลัพธ์:

[ -1, 0, 1, 2, 3, 4, 5 ]
=====
[ -1, 0, 1, 2, 3, 4, 5 ]
undefined
=====
[ -1, 0, 1, 2, 3, 4, 5 ]
[ 0, 1, 2, 3, 4, 5, 6 ]

ฉันไม่สามารถเข้าใจว่าทำไมการใช้practiceค่าเปลี่ยนแปลงไปb ฉันขอโทษหากนี่เป็นคำถามที่ไร้สาระ แต่ฉันค่อนข้างใหม่ในภาษานี้และคำตอบที่ฉันพบจนถึงตอนนี้ไม่ตรงใจฉันundefined


49
มันง่ายมาก: .map ส่งคืนอาร์เรย์ใหม่ในขณะที่.forEach ไม่ส่งคืนอะไรเลย โดยทั่วไปถ้าคุณต้องการที่จะได้รับการปรับเปลี่ยนรูปแบบของอาเรย์ก่อนหน้านี้คุณใช้ถ้าคุณไม่ต้องการที่คุณใช้.map .forEach
user4642212


@ Xufox - ฉันแดงหัวข้อนี้ก่อนสร้างใหม่ แต่คำตอบไม่ตรงใจฉัน
DzikiChrzan

อย่าเพิ่งพูดว่ามันไม่ทำให้คุณพอใจ มันไม่ตอบคำถามของคุณได้อย่างไร (คุณอ่านคำตอบทั้งหมดแล้วหรือยัง?)? คำถามเฉพาะของคุณที่ไม่ครอบคลุมโดยเป้าหมายซ้ำที่เสนอคืออะไร
user4642212

@Xufox คำถามนั้นเกี่ยวข้องกับฟังก์ชันที่ใช้งานได้เองและไม่เกี่ยวกับฟังก์ชัน ES5 ที่เป็นมาตรฐาน
โผล่

คำตอบ:


148

พวกเขาไม่ได้เป็นหนึ่งเดียวกัน ให้ฉันอธิบายความแตกต่าง

forEach: สิ่งนี้จะวนซ้ำในรายการและใช้การดำเนินการบางอย่างที่มีผลข้างเคียงกับสมาชิกแต่ละรายชื่อ (ตัวอย่าง: บันทึกทุกรายการลงในฐานข้อมูล)

map: สิ่งนี้วนซ้ำในรายการเปลี่ยนสมาชิกแต่ละคนของรายการนั้นและส่งคืนรายการอื่นที่มีขนาดเท่ากันกับสมาชิกที่แปลงแล้ว (ตัวอย่าง: การเปลี่ยนรายการสตริงเป็นตัวพิมพ์ใหญ่)

อ้างอิง

Array.prototype.forEach () - JavaScript | MDN

Array.prototype.map () - JavaScript | MDN


5
และเช่นเดียวกับที่ Xufox กล่าว - สำหรับแต่ละคนไม่ได้ส่งคืนอะไรเลย ขอบคุณที่ช่วยเหลือ! ฉันจะทำเครื่องหมายคำตอบนี้ใน 10 นาที
DzikiChrzan

1
รายการคืนแผนที่และสำหรับแต่ละไม่ ตกลง
Ashad Nasim

62
  • Array.forEach “ เรียกใช้ฟังก์ชันที่ให้มาหนึ่งครั้งต่อองค์ประกอบอาร์เรย์”

  • Array.map “ สร้างอาร์เรย์ใหม่ด้วยผลลัพธ์ของการเรียกใช้ฟังก์ชันที่มีให้ในทุกองค์ประกอบในอาร์เรย์นี้”

เลยforEachไม่คืนอะไรจริง เพียงแค่เรียกใช้ฟังก์ชันสำหรับแต่ละองค์ประกอบอาร์เรย์จากนั้นก็เสร็จสิ้น ดังนั้นสิ่งที่คุณกลับมาภายในฟังก์ชันที่เรียกว่าจะถูกทิ้งไป

ในทางกลับmapกันจะเรียกใช้ฟังก์ชันสำหรับแต่ละองค์ประกอบอาร์เรย์ในทำนองเดียวกัน แต่แทนที่จะทิ้งค่าที่ส่งกลับไปมันจะจับมันและสร้างอาร์เรย์ใหม่ของค่าที่ส่งคืนเหล่านั้น

นอกจากนี้ยังหมายความว่าคุณสามารถใช้mapที่ใดก็ตามที่คุณกำลังใช้forEachแต่คุณยังไม่ควรทำอย่างนั้นเพื่อให้คุณจะไม่เก็บค่าที่ส่งคืนโดยไม่มีวัตถุประสงค์ใด ๆ มันมีประสิทธิภาพมากกว่าที่จะไม่รวบรวมหากคุณไม่ต้องการ


หมายเหตุ: ในปี 2015 จะมีการโต้แย้งว่าforEachจะ "มีประสิทธิภาพ" มากกว่าmapโดยเฉพาะอย่างยิ่งหากจำเป็นต้องใช้ polyfill เพื่อรองรับforEachเบราว์เซอร์รุ่นเก่า (IE8 หรือ 9) คุณไม่จำเป็นต้องกำหนดการส่งคืนmapสิ่งใด ๆ มูลค่าที่ส่งคืนควรได้รับขยะที่รวบรวมทันทีหลังจากmapส่งคืนเมื่อmapไม่ได้กำหนดการส่งคืน
cowbert

3
@cowbert เพียงเพราะมีบางอย่างถูกเก็บรวบรวมทันทีนั่นไม่ได้หมายความว่าคุณจะไม่ได้รับผลกระทบจากการจัดสรรที่จำเป็น ดังนั้นแนวคิดforEachจะยังคงมีประสิทธิภาพมากกว่าและเหมาะกับงานที่คุณไม่จำเป็นต้องรวบรวมผลลัพธ์ และฉันไม่รู้เกี่ยวกับคุณ แต่ในปี 2015 ฉันไม่ได้พัฒนาสำหรับ IE8 อีกต่อไป (ซึ่ง btw. ยังไม่รองรับ); และการสนับสนุน IE9 + และหนึ่งเดือนหลังจากคำตอบของฉัน Microsoft ยุติการสนับสนุนเบราว์เซอร์เหล่านั้น mapforEach
โผล่

ทั้ง forEach และแผนที่รับประกันว่าจะประมวลผลองค์ประกอบในลำดับเดียวกันหรือไม่
Quentin 2

1
@ Quentin2 ใช่เช่นกันฟังก์ชั่นทั้งสองเป็นแบบซิงโครนัสดังนั้นmapและการforEachโทรจะกลับมาก็ต่อเมื่ออาร์เรย์ทั้งหมดถูกวนซ้ำและมีการเรียกกลับสำหรับแต่ละรายการ
โผล่

25
+ + ---------------- -------------------------------- ----- + --------------------------------------- +
| | foreach | แผนที่ |
+ + ---------------- -------------------------------- ----- + --------------------------------------- +
| ฟังก์ชั่น | ดำเนินการที่กำหนดในแต่ละ | ดำเนินการ "การเปลี่ยนแปลง" ที่กำหนดเมื่อ |
| | องค์ประกอบของอาร์เรย์ | "คัดลอก" ของแต่ละองค์ประกอบ |
+ + ---------------- -------------------------------- ----- + --------------------------------------- +
| ส่งคืนค่า | ส่งคืนไม่ได้กำหนด | ส่งคืนอาร์เรย์ใหม่ด้วย tranformed |
| | | องค์ประกอบออกจากอาร์เรย์เดิม |
| | | ไม่เปลี่ยนแปลง |
+ + ---------------- -------------------------------- ----- + --------------------------------------- +
| ที่ต้องการ | ดำเนินการแบบไม่แปลงร่างเช่น | การรับอาร์เรย์ที่มีเอาต์พุตของ |
| สถานการณ์การใช้งาน | การประมวลผลในแต่ละองค์ประกอบ | การประมวลผลบางอย่างเสร็จสิ้นในแต่ละองค์ประกอบ |
| และตัวอย่าง | | ของอาร์เรย์ |
| | ตัวอย่างเช่นการบันทึกองค์ประกอบทั้งหมดใน | |
| | ฐานข้อมูล | ตัวอย่างเช่นการได้รับอาร์เรย์ของ |
| | | ความยาวของแต่ละสตริงใน |
| | | อาร์เรย์ |
+ + ---------------- -------------------------------- ----- + --------------------------------------- +

โปรดแก้ไขโพสต์ของคุณและแสดงข้อความจริงแทนรูปภาพ ผู้อื่นไม่สามารถคัดลอกและวางจากรูปภาพของคุณหรือค้นหาภายในรูปภาพของคุณหรือช่วยปรับปรุงเนื้อหาข้อความในรูปภาพ ดูรายละเอียดได้ที่นี่ ขอบคุณ.
ปาง

3
สิ่งนี้อาจช่วยคุณวาดตารางศิลปะ ASCII: webapps.stackexchange.com/q/6700/126269
ปาง

16

ความแตกต่างหลักที่คุณต้องรู้คือ.map()ส่งคืนอาร์เรย์ใหม่ในขณะที่.forEach()ไม่ได้ นั่นคือเหตุผลที่คุณเห็นความแตกต่างนั้นในผลลัพธ์ .forEach()เพียงแค่ดำเนินการกับทุกค่าในอาร์เรย์

อ่าน:

คุณอาจต้องการตรวจสอบ: - Array.prototype.every()- JavaScript | MDN


7

forEach: หากคุณต้องการดำเนินการกับองค์ประกอบของ Array และเหมือนกับที่คุณใช้สำหรับการวนซ้ำ ผลลัพธ์ของวิธีนี้ไม่ได้ทำให้เรามีการซื้อผลผลิตเพียงแค่วนซ้ำองค์ประกอบ

แผนที่: หากคุณต้องการดำเนินการกับองค์ประกอบของอาร์เรย์และคุณต้องการเก็บผลลัพธ์ของการกระทำของคุณลงใน Array สิ่งนี้คล้ายกับการวนซ้ำภายในฟังก์ชันที่ส่งคืนผลลัพธ์หลังจากการวนซ้ำแต่ละครั้ง

หวังว่านี่จะช่วยได้


5

ความแตกต่างอยู่ที่สิ่งที่พวกเขากลับมา หลังจากดำเนินการ:

arr.map()

ส่งคืนอาร์เรย์ขององค์ประกอบที่เกิดจากฟังก์ชันที่ประมวลผล ในขณะที่:

arr.forEach()

ส่งคืนไม่ได้กำหนด


5

การวิเคราะห์ประสิทธิภาพ สำหรับลูปทำงานได้เร็วกว่าการแมปหรือ foreach เนื่องจากจำนวนองค์ประกอบในอาร์เรย์เพิ่มขึ้น

let array = [];
for (var i = 0; i < 20000000; i++) {
  array.push(i)
}

console.time('map');
array.map(num => {
  return num * 4;
});
console.timeEnd('map');


console.time('forEach');
array.forEach((num, index) => {
  return array[index] = num * 4;
});
console.timeEnd('forEach');

console.time('for');
for (i = 0; i < array.length; i++) {
  array[i] = array[i] * 2;

}
console.timeEnd('for');

นี่คือผลลัพธ์ในคอมพิวเตอร์ของฉัน:map: 1642ms forEach: 885ms for: 748ms
Flavio Vilante

2

ความแตกต่างระหว่าง Foreach และแผนที่:

แผนที่ () : หากคุณใช้แผนที่แผนที่สามารถส่งคืนอาร์เรย์ใหม่โดยการวนซ้ำอาร์เรย์หลัก

Foreach () : หากคุณใช้ Foreach มันจะไม่สามารถส่งคืนข้อมูลใด ๆ สำหรับแต่ละอาร์เรย์หลักซ้ำได้

ลิงก์ useFul : ใช้ลิงก์นี้เพื่อทำความเข้าใจความแตกต่าง

https://codeburst.io/javascript-map-vs-foreach-f38111822c0f


1

สิ่งหนึ่งที่ต้องชี้ให้เห็นก็คือ foreach จะข้ามค่าที่ไม่ได้กำหนดค่าเริ่มต้นในขณะที่แผนที่ไม่มี

var arr = [1, , 3];

arr.forEach(function(element) {
    console.log(element);
});
//Expected output: 1 3

console.log(arr.map(element => element));
//Expected output: [1, undefined, 3];

0

ความแตกต่างระหว่าง forEach () และแผนที่ ()

forEach ()เพียงแค่วนผ่านองค์ประกอบ มันพ่นค่าที่ส่งคืนออกไปและส่งคืนค่าที่ไม่ได้กำหนดไว้เสมอผลลัพธ์ของวิธีนี้ไม่ได้ให้ผลลัพธ์แก่เรา

map ()วนซ้ำองค์ประกอบจัดสรรหน่วยความจำและเก็บค่าที่ส่งคืนโดยการวนซ้ำอาร์เรย์หลัก

ตัวอย่าง:

   var numbers = [2,3,5,7];

   var forEachNum = numbers.forEach(function(number){
      return number
   })
   console.log(forEachNum)
   //output undefined

   var mapNum = numbers.map(function(number){
      return number
   })
   console.log(mapNum)
   //output [2,3,5,7]

แผนที่ () เร็วกว่า forEach ()


0

แผนที่ส่งคืนโดยปริยายในขณะที่ forEach ไม่

นี่คือเหตุผลที่เมื่อคุณกำลังเข้ารหัสเป็นโปรแกรม JSX คุณมักจะใช้แผนที่แทนforEach เพื่อแสดงเนื้อหาในการตอบสนอง


0

forEach () :

ค่าส่งคืน: ไม่ได้กำหนด

originalArray: แก้ไขหลังจากการเรียกใช้เมธอด

แผนที่ () :

ค่าที่ส่งคืน: อาร์เรย์ใหม่ที่เติมด้วยผลลัพธ์ของการเรียกใช้ฟังก์ชันที่มีให้ในทุกองค์ประกอบในอาร์เรย์การเรียก

originalArray: ไม่ได้รับการแก้ไขหลังจากการเรียกใช้เมธอด

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.