ฉันจะวนซ้ำรายการทั้งหมดในอาร์เรย์โดยใช้ JavaScript ได้อย่างไร
ฉันคิดว่ามันเป็นเช่นนี้:
forEach(instance in theArray)
theArray
อาร์เรย์ของฉันอยู่ที่ไหนแต่ดูเหมือนว่าจะไม่ถูกต้อง
i < len
และi++
สามารถทำได้โดยเครื่องยนต์มากกว่าโดยล่าม.)
ฉันจะวนซ้ำรายการทั้งหมดในอาร์เรย์โดยใช้ JavaScript ได้อย่างไร
ฉันคิดว่ามันเป็นเช่นนี้:
forEach(instance in theArray)
theArray
อาร์เรย์ของฉันอยู่ที่ไหนแต่ดูเหมือนว่าจะไม่ถูกต้อง
i < len
และi++
สามารถทำได้โดยเครื่องยนต์มากกว่าโดยล่าม.)
คำตอบ:
TL; DR
for-in
จนกว่าคุณจะใช้มันด้วยการป้องกันหรืออย่างน้อยก็รู้ว่าทำไมมันอาจกัดคุณโดยปกติแล้วการเดิมพันที่ดีที่สุดของคุณ
แต่ยังมีอีกมากมายให้สำรวจอ่านต่อ ...
JavaScript มีซีแมนทิกส์ที่ทรงพลังสำหรับการวนลูปผ่านอาร์เรย์และวัตถุคล้ายอาร์เรย์ ฉันแบ่งคำตอบออกเป็นสองส่วน: ตัวเลือกสำหรับอาร์เรย์ของแท้และตัวเลือกสำหรับสิ่งต่าง ๆเช่นอาเรย์arguments
วัตถุออบเจกต์อื่น ๆ (ES2015 +) คอลเลกชัน DOM และอื่น ๆ
ฉันได้อย่างรวดเร็วจะได้ทราบว่าคุณสามารถใช้ ES2015 ตัวเลือกในขณะนี้แม้ในเครื่องมือ ES5 โดยtranspiling ES2015 เพื่อ ES5 ค้นหา "transpiling ES2015" / "transpiling ES6" สำหรับข้อมูลเพิ่มเติม ...
เอาล่ะมาดูตัวเลือกของเรา:
คุณมีสามตัวเลือกในECMAScript 5 ("ES5") รุ่นที่ได้รับการสนับสนุนอย่างกว้างขวางที่สุดในขณะนี้และอีกสองตัวเลือกเพิ่มเติมในECMAScript 2015 ("ES2015", "ES6"):
forEach
และที่เกี่ยวข้อง (ES5 +)for
วนรอบง่าย ๆfor-in
อย่างถูกต้องfor-of
(ใช้ตัววนซ้ำโดยนัย) (ES2015 +)รายละเอียด:
forEach
และที่เกี่ยวข้องในสภาพแวดล้อมที่ทันสมัยราง ๆ (ดังนั้นไม่ใช่ IE8) ที่คุณสามารถเข้าถึงArray
คุณลักษณะที่เพิ่มโดย ES5 (โดยตรงหรือใช้โพลีฟิล) คุณสามารถใช้forEach
( spec
| MDN
):
var a = ["a", "b", "c"];
a.forEach(function(entry) {
console.log(entry);
});
forEach
ยอมรับฟังก์ชั่นการโทรกลับและเลือกที่จะใช้เป็นค่าthis
เมื่อโทรกลับที่โทร (ไม่ได้ใช้ด้านบน) การเรียกกลับถูกเรียกสำหรับแต่ละรายการในอาร์เรย์ตามลำดับโดยข้ามรายการที่ไม่มีอยู่ในอาร์เรย์กระจัดกระจาย แม้ว่าฉันจะใช้เพียงอาร์กิวเมนต์เดียวด้านบน แต่การโทรกลับถูกเรียกด้วยสาม: ค่าของแต่ละรายการดัชนีของรายการนั้นและการอ้างอิงไปยังอาร์เรย์ที่คุณวนซ้ำ (ในกรณีที่ฟังก์ชันของคุณไม่มีประโยชน์ )
ถ้าคุณไม่สนับสนุนเบราว์เซอร์ที่ล้าสมัยอย่าง IE8 (ซึ่ง NetApps แสดงที่ส่วนแบ่งการตลาดมากกว่า 4% จากการเขียนนี้ในเดือนกันยายน 2559) คุณสามารถใช้งานได้อย่างมีความสุขforEach
ในหน้าเว็บเอนกประสงค์ที่ไม่มีหน้าจอ หากคุณต้องการรองรับเบราว์เซอร์ที่ล้าสมัยการ shimming / polyfilling forEach
สามารถทำได้อย่างง่ายดาย (ค้นหา "es5 shim" สำหรับตัวเลือกต่างๆ)
forEach
มีประโยชน์ที่คุณไม่ต้องประกาศการจัดทำดัชนีและตัวแปรค่าในขอบเขตที่มีเนื่องจากพวกเขากำลังให้เป็นข้อโต้แย้งกับฟังก์ชั่นการทำซ้ำและเพื่อกำหนดขอบเขตอย่างมากเพียงแค่การทำซ้ำนั้น
หากคุณกังวลเกี่ยวกับค่าใช้จ่ายรันไทม์ในการโทรเรียกใช้ฟังก์ชั่นสำหรับแต่ละรายการอาเรย์ รายละเอียด
นอกจากนี้ยังforEach
มีฟังก์ชั่น "วนรอบพวกมันทั้งหมด" แต่ ES5 ได้กำหนดประโยชน์อื่น ๆ ไว้หลายอย่าง "ทำงานในแบบของคุณผ่านฟังก์ชันอาร์เรย์และทำสิ่งต่าง ๆ " ซึ่งรวมถึง:
every
(หยุดการวนซ้ำในครั้งแรกที่โทรกลับfalse
หรือบางสิ่งบางอย่างผิดพลาด)some
(หยุดวนซ้ำในครั้งแรกที่โทรกลับtrue
หรือสิ่งที่เป็นความจริง)filter
(สร้างอาร์เรย์ใหม่ซึ่งรวมถึงองค์ประกอบที่ฟังก์ชันตัวกรองส่งคืนtrue
และละเว้นอาร์เรย์ที่ส่งคืนfalse
)map
(สร้างอาร์เรย์ใหม่จากค่าที่ส่งคืนโดยการเรียกกลับ)reduce
(สร้างค่าโดยการโทรติดต่อกลับซ้ำ ๆ ผ่านค่าก่อนหน้าดูข้อมูลจำเพาะสำหรับรายละเอียดมีประโยชน์สำหรับการรวมเนื้อหาของอาร์เรย์และสิ่งอื่น ๆ )reduceRight
(เช่นreduce
แต่ทำงานในลำดับมากไปน้อยมากกว่าเรียงลำดับขึ้นมา)for
วนรอบง่าย ๆบางครั้งวิธีเก่า ๆ นั้นดีที่สุด:
var index;
var a = ["a", "b", "c"];
for (index = 0; index < a.length; ++index) {
console.log(a[index]);
}
ถ้าความยาวของอาร์เรย์จะไม่เปลี่ยนแปลงในช่วงห่วงและก็ในรหัสประสิทธิภาพที่สำคัญ (น่า) รุ่นที่ซับซ้อนกว่าเล็กน้อยโลภความยาวขึ้นหน้าอาจจะมีเล็ก ๆบิตเร็วขึ้น:
var index, len;
var a = ["a", "b", "c"];
for (index = 0, len = a.length; index < len; ++index) {
console.log(a[index]);
}
และ / หรือนับถอยหลัง:
var index;
var a = ["a", "b", "c"];
for (index = a.length - 1; index >= 0; --index) {
console.log(a[index]);
}
แต่ด้วยเครื่องมือจาวาสคริปต์ที่ทันสมัยมันหายากที่คุณจะต้องแสดงให้เห็นถึงบิตสุดท้ายของน้ำผลไม้
ใน ES2015 และสูงกว่าคุณสามารถสร้างดัชนีและค่าตัวแปรของคุณแบบโลคัลได้for
:
let a = ["a", "b", "c"];
for (let index = 0; index < a.length; ++index) {
let value = a[index];
console.log(index, value);
}
//console.log(index); // would cause "ReferenceError: index is not defined"
//console.log(value); // would cause "ReferenceError: value is not defined"
และเมื่อคุณทำเช่นนั้นไม่เพียงvalue
แต่index
จะถูกสร้างขึ้นใหม่สำหรับการวนซ้ำแต่ละครั้งความหมายการปิดที่สร้างขึ้นในร่างกายลูปจะอ้างอิงถึงการสร้างindex
(และvalue
) สำหรับการทำซ้ำเฉพาะนั้น:
let divs = document.querySelectorAll("div");
for (let index = 0; index < divs.length; ++index) {
divs[index].addEventListener('click', e => {
console.log("Index is: " + index);
});
}
หากคุณมีห้า divs คุณจะได้รับ "ดัชนีคือ: 0" หากคุณคลิกที่แรกและ "ดัชนีคือ: 4" ถ้าคุณคลิกที่สุดท้าย นี้ไม่ได้ทำงานถ้าคุณใช้แทนvar
let
for-in
อย่างถูกต้องคุณจะได้รับคนที่บอกให้คุณใช้for-in
แต่นั่นไม่ใช่สิ่งที่for-in
เป็น for-in
วนซ้ำผ่านคุณสมบัติที่นับได้ของวัตถุไม่ใช่ดัชนีของอาร์เรย์ ไม่รับประกันคำสั่งไม่แม้แต่ใน ES2015 (ES6) ES2015 + กำหนดคำสั่งให้กับคุณสมบัติของวัตถุ (ผ่าน[[OwnPropertyKeys]]
, [[Enumerate]]
และสิ่งที่ใช้พวกเขาชอบObject.getOwnPropertyKeys
) แต่ไม่ได้กำหนดว่าfor-in
จะทำตามคำสั่งนั้น แม้ว่า ES2020 ทำ (รายละเอียดในคำตอบอื่น ๆนี้)
กรณีการใช้งานจริงสำหรับfor-in
อาร์เรย์เท่านั้น:
ดูจากตัวอย่างแรกเท่านั้น: คุณสามารถใช้for-in
เพื่อเยี่ยมชมองค์ประกอบอาเรย์เหล่านั้นหากคุณใช้การป้องกันที่เหมาะสม:
// `a` is a sparse array
var key;
var a = [];
a[0] = "a";
a[10] = "b";
a[10000] = "c";
for (key in a) {
if (a.hasOwnProperty(key) && // These checks are
/^0$|^[1-9]\d*$/.test(key) && // explained
key <= 4294967294 // below
) {
console.log(a[key]);
}
}
บันทึกการตรวจสอบสามรายการ:
วัตถุนั้นมีคุณสมบัติเป็นของตนเองโดยใช้ชื่อนั้น (ไม่ใช่สิ่งที่สืบทอดมาจากต้นแบบ) และ
ว่ากุญแจนั้นเป็นตัวเลขทศนิยมทั้งหมด (เช่นรูปแบบสตริงปกติไม่ใช่สัญลักษณ์ทางวิทยาศาสตร์) และ
นั่นคือค่าของคีย์เมื่อ coerced กับตัวเลขคือ <= 2 ^ 32 - 2 (ซึ่งคือ 4,294,967,294) หมายเลขนั้นมาจากไหน มันเป็นส่วนหนึ่งของความหมายของดัชนีอาร์เรย์ในสเปค ตัวเลขอื่น ๆ (ไม่ใช่ตัวเลขจำนวนเต็มจำนวนลบมากกว่า 2 ^ 32 - 2) ไม่ใช่ดัชนีอาร์เรย์ เหตุผลที่เป็น 2 ^ 32 - 2คือทำให้ค่าดัชนีมากที่สุดหนึ่งต่ำกว่า 2 ^ 32 - 1ซึ่งเป็นค่าสูงสุดที่อาร์เรย์length
สามารถมีได้ (เช่นความยาวของอาเรย์นั้นพอดีกับจำนวนเต็ม 32 บิตที่ไม่ได้ลงชื่อ) (อุปกรณ์ประกอบฉากของ RobG เพื่อชี้ให้เห็นในความคิดเห็นในโพสต์บล็อกของฉันว่าการทดสอบก่อนหน้าของฉันไม่ถูกต้อง)
คุณจะไม่ทำอย่างนั้นในรหัสแบบอินไลน์แน่นอน คุณต้องการเขียนฟังก์ชันยูทิลิตี้ บางที:
for-of
(ใช้ตัววนซ้ำโดยนัย) (ES2015 +)ES2015 เพิ่มตัววนซ้ำใน JavaScript วิธีที่ง่ายที่สุดในการใช้ตัววนซ้ำคือfor-of
คำสั่งใหม่ ดูเหมือนว่านี้:
const a = ["a", "b", "c"];
for (const val of a) {
console.log(val);
}
ภายใต้หน้าปกที่ได้รับตัววนซ้ำจากอาร์เรย์และวนซ้ำผ่านมันรับค่าจากมัน นี่ไม่มีปัญหาที่ใช้for-in
มีเนื่องจากจะใช้ตัววนซ้ำที่กำหนดโดยวัตถุ (อาร์เรย์) และอาร์เรย์กำหนดว่าตัววนซ้ำของพวกเขาวนซ้ำผ่านรายการ (ไม่ใช่คุณสมบัติ) ซึ่งแตกต่างจากfor-in
ใน ES5 ลำดับที่มีการเยี่ยมชมรายการเป็นลำดับตัวเลขของดัชนีของพวกเขา
บางครั้งคุณอาจต้องการที่จะใช้iterator อย่างชัดเจน คุณสามารถทำได้เช่นกันแม้ว่ามันจะเป็น clunkier for-of
กว่ามาก ดูเหมือนว่านี้:
const a = ["a", "b", "c"];
const it = a.values();
let entry;
while (!(entry = it.next()).done) {
console.log(entry.value);
}
iterator เป็นวัตถุที่ตรงกับนิยามของ Iterator ในสเปค next
วิธีการของมันจะส่งคืนวัตถุผลลัพธ์ใหม่ทุกครั้งที่คุณเรียกมัน วัตถุผลลัพธ์มีคุณสมบัติdone
บอกเราว่ามันทำเสร็จแล้วและคุณสมบัติที่value
มีค่าสำหรับการทำซ้ำนั้น ( done
เป็นตัวเลือกว่ามันจะเป็นfalse
, value
เป็นตัวเลือกว่ามันจะเป็นundefined
.)
ความหมายของการvalue
แตกต่างกันไปขึ้นอยู่กับตัววนซ้ำ; สนับสนุนอาร์เรย์ (อย่างน้อย) สามฟังก์ชันที่ส่งคืนตัววนซ้ำ:
values()
: นี่คือสิ่งที่ฉันใช้ข้างต้น มันกลับ iterator ที่แต่ละvalue
คือรายการอาร์เรย์สำหรับการย้ำว่า ( "a"
, "b"
และ"c"
ในตัวอย่างก่อนหน้านี้)keys()
: กลับ iterator ที่แต่ละvalue
เป็นกุญแจสำคัญสำหรับการย้ำว่า (ดังนั้นสำหรับเราa
ข้างต้นว่าจะ"0"
แล้ว"1"
แล้ว"2"
)entries()
: ส่งคืนตัววนซ้ำที่แต่ละvalue
อาร์เรย์เป็นแบบฟอร์ม[key, value]
สำหรับการทำซ้ำนั้นนอกเหนือจากอาร์เรย์ที่แท้จริงแล้วยังมีวัตถุที่เหมือนอาร์เรย์ที่มีlength
คุณสมบัติและคุณสมบัติที่มีชื่อที่เป็นตัวเลขNodeList
เช่นอินสแตนซ์arguments
วัตถุ ฯลฯ เราจะวนรอบเนื้อหาได้อย่างไร
อย่างน้อยที่สุด, และอาจเป็นไปได้หรือมากที่สุด, ของอาเรย์ข้างต้นมักใช้กับวัตถุที่มีลักษณะคล้ายอาเรย์อย่างเท่าเทียมกัน:
การใช้งานforEach
และที่เกี่ยวข้อง (ES5 +)
ฟังก์ชั่นต่างๆบนArray.prototype
คือ "เจตนาทั่วไป" และมักจะสามารถนำมาใช้ในอาร์เรย์เหมือนวัตถุผ่านหรือFunction#call
Function#apply
(ดูCaveat สำหรับวัตถุที่โฮสต์ให้ในตอนท้ายของคำตอบนี้ แต่มันเป็นปัญหาที่หายาก)
สมมติว่าคุณต้องการที่จะใช้forEach
ในNode
ของchildNodes
สถานที่ให้บริการ คุณต้องการทำสิ่งนี้:
Array.prototype.forEach.call(node.childNodes, function(child) {
// Do something with `child`
});
หากคุณจะทำสิ่งนั้นมากคุณอาจต้องการคัดลอกการอ้างอิงฟังก์ชันลงในตัวแปรเพื่อนำมาใช้ซ้ำเช่น:
// (This is all presumably in some scoping function)
var forEach = Array.prototype.forEach;
// Then later...
forEach.call(node.childNodes, function(child) {
// Do something with `child`
});
ใช้การfor
วนรอบง่าย ๆ
เห็นได้ชัดว่าการfor
วนซ้ำอย่างง่ายนำไปใช้กับวัตถุที่เหมือนอาร์เรย์
ใช้for-in
อย่างถูกต้อง
for-in
ด้วยมาตรการป้องกันเช่นเดียวกับอาร์เรย์ควรทำงานกับวัตถุที่เหมือนอาร์เรย์เช่นกัน ข้อแม้สำหรับวัตถุที่โฮสต์ให้ใน # 1 ข้างต้นอาจนำไปใช้
ใช้for-of
(ใช้ตัววนซ้ำโดยนัย) (ES2015 +)
for-of
ใช้ตัววนซ้ำที่จัดเตรียมโดยวัตถุ (ถ้ามี) ซึ่งรวมถึงวัตถุที่โฮสต์ให้ ตัวอย่างเช่นข้อมูลจำเพาะสำหรับNodeList
จากquerySelectorAll
ได้รับการอัปเดตเพื่อรองรับการทำซ้ำ สเป็คสำหรับHTMLCollection
จากgetElementsByTagName
ไม่ได้
ใช้ตัววนซ้ำอย่างชัดเจน (ES2015 +)
ดู # 4
ในบางครั้งคุณอาจต้องการแปลงวัตถุคล้ายอาร์เรย์ให้เป็นอาร์เรย์จริง การทำเช่นนั้นเป็นเรื่องง่ายอย่างน่าประหลาดใจ:
ใช้slice
วิธีการของอาร์เรย์
เราสามารถใช้slice
วิธีการของอาร์เรย์ซึ่งเช่นเดียวกับวิธีอื่น ๆ ที่กล่าวถึงข้างต้นคือ "จงใจทั่วไป" และสามารถใช้กับวัตถุที่มีลักษณะคล้ายอาร์เรย์ได้ดังนี้:
var trueArray = Array.prototype.slice.call(arrayLikeObject);
ตัวอย่างเช่นถ้าเราต้องการแปลง a NodeList
เป็นอาร์เรย์ที่แท้จริงเราสามารถทำได้:
var divs = Array.prototype.slice.call(document.querySelectorAll("div"));
ดูCaveat สำหรับวัตถุที่ให้บริการโฮสต์ด้านล่าง โดยเฉพาะอย่างยิ่งโปรดทราบว่าสิ่งนี้จะล้มเหลวใน IE8 และรุ่นก่อนหน้าซึ่งไม่อนุญาตให้คุณใช้ออบเจ็กต์ที่โฮสต์จัดไว้ให้this
อย่างนั้น
ใช้ไวยากรณ์การแพร่กระจาย ( ...
)
นอกจากนี้ยังเป็นไปได้ที่จะใช้ไวยากรณ์การแพร่กระจายของ ES2015 กับเครื่องมือ JavaScript ที่สนับสนุนคุณสมบัตินี้ เช่นfor-of
นี้ใช้ตัววนซ้ำโดยวัตถุ (ดู # 4 ในส่วนก่อนหน้า):
var trueArray = [...iterableObject];
ตัวอย่างเช่นถ้าเราต้องการแปลงเป็นNodeList
อาร์เรย์จริงด้วยไวยากรณ์การแพร่กระจายนี้จะค่อนข้างรวบรัด:
var divs = [...document.querySelectorAll("div")];
ใช้ Array.from
Array.from
(spec) | (MDN) (ES2015 + แต่เป็นโพลีฟิลอย่างง่ายดาย) สร้างอาร์เรย์จากวัตถุที่มีลักษณะคล้ายอาร์เรย์เลือกที่จะส่งผ่านรายการผ่านฟังก์ชันการแมปก่อน ดังนั้น:
var divs = Array.from(document.querySelectorAll("div"));
หรือถ้าคุณต้องการที่จะได้รับอาร์เรย์ของชื่อแท็กขององค์ประกอบที่มีชั้นเรียนที่คุณต้องการใช้ฟังก์ชั่นการทำแผนที่:
// Arrow function (ES2015):
var divs = Array.from(document.querySelectorAll(".some-class"), element => element.tagName);
// Standard function (since `Array.from` can be shimmed):
var divs = Array.from(document.querySelectorAll(".some-class"), function(element) {
return element.tagName;
});
หากคุณใช้Array.prototype
ฟังก์ชั่นที่มีวัตถุคล้ายอาร์เรย์ที่โฮสต์ให้บริการ (รายการ DOM และสิ่งอื่น ๆ ที่ให้บริการโดยเบราว์เซอร์แทนที่จะเป็นเครื่องมือ JavaScript) คุณต้องแน่ใจว่าได้ทดสอบในสภาพแวดล้อมเป้าหมายของคุณเพื่อให้แน่ใจว่าวัตถุที่โฮสต์ให้ทำงาน . ส่วนใหญ่ทำงานได้อย่างถูกต้อง (ตอนนี้) แต่สิ่งสำคัญคือการทดสอบ เหตุผลก็คือArray.prototype
วิธีการส่วนใหญ่ที่คุณต้องการใช้นั้นขึ้นอยู่กับออบเจ็กต์ที่โฮสต์จัดเตรียมไว้ให้ซึ่งเป็นคำตอบที่ถูกต้องสำหรับการ[[HasProperty]]
ดำเนินการเชิงนามธรรม จากการเขียนนี้เบราว์เซอร์ทำงานได้ดีมากในเรื่องนี้ แต่ข้อมูลจำเพาะ 5.1 อนุญาตให้มีความเป็นไปได้ที่วัตถุที่โฮสต์จัดหาอาจไม่ตรงไปตรงมา มันอยู่ใน§8.6.2หลายย่อหน้าด้านล่างของตารางขนาดใหญ่ใกล้กับจุดเริ่มต้นของส่วนนั้น) ซึ่งมันบอกว่า:
วัตถุโฮสต์อาจใช้วิธีการภายในเหล่านี้ในลักษณะใด ๆ เว้นแต่จะระบุไว้เป็นอย่างอื่น ตัวอย่างเช่นความเป็นไปได้อย่างหนึ่งคือ
[[Get]]
และ[[Put]]
สำหรับวัตถุโฮสต์ที่แน่นอนเรียกและเก็บค่าคุณสมบัติ แต่[[HasProperty]]
สร้างเท็จเสมอ
(ผมไม่สามารถหาคำฟุ่มเฟือยเทียบเท่าในสเป็ค ES2015 แต่ก็ผูกพันกับยังคงเป็นกรณี.) อีกครั้งขณะที่เขียนนี้ร่วมกันเป็นเจ้าภาพที่ให้อาร์เรย์เหมือนวัตถุในเบราว์เซอร์ที่ทันสมัย [ NodeList
กรณีตัวอย่าง] ทำด้าม[[HasProperty]]
ถูกต้อง แต่สิ่งสำคัญคือการทดสอบ)
.forEach
ไม่สามารถแยกได้อย่างมีประสิทธิภาพ คุณต้องโยนข้อยกเว้นเพื่อทำการหยุดพัก
some
ถ้าคุณต้องการที่จะทำลายห่วงคุณสามารถใช้ (ฉันอยากจะอนุญาตให้ทำลายforEach
ด้วยเช่นกัน แต่พวกเขาอืมไม่ได้ถามฉัน ;-))
,
หลังจากที่ไม่ได้เป็นk=0
;
โปรดจำไว้ว่าการเขียนโปรแกรมมีหลายสิ่งหลายอย่างหนึ่งในนั้นคือใส่ใจในรายละเอียด ... :-)
length
ไม่ใช่วิธี) :-)
หมายเหตุ : คำตอบนี้ล้าสมัยอย่างสิ้นหวัง สำหรับวิธีการที่ทันสมัยมากขึ้นดูที่วิธีการที่มีอยู่บนอาร์เรย์ วิธีการที่น่าสนใจอาจเป็น:
วิธีมาตรฐานในการย้ำอาร์เรย์ในJavaScriptคือ vanilla for
-loop:
var length = arr.length,
element = null;
for (var i = 0; i < length; i++) {
element = arr[i];
// Do something with element
}
อย่างไรก็ตามโปรดทราบว่าวิธีการนี้ดีเฉพาะถ้าคุณมีอาร์เรย์ที่หนาแน่นและแต่ละดัชนีจะถูกครอบครองโดยองค์ประกอบ หากอาร์เรย์จะเบาบางแล้วคุณสามารถใช้เป็นปัญหาประสิทธิภาพการทำงานด้วยวิธีนี้เนื่องจากคุณจะย้ำกว่ามากของดัชนีที่ไม่ได้จริงๆอยู่ในอาร์เรย์ ในกรณีนี้ a for .. in
-loop อาจเป็นแนวคิดที่ดีกว่า อย่างไรก็ตามคุณต้องใช้การป้องกันที่เหมาะสมเพื่อให้แน่ใจว่ามีการดำเนินการเฉพาะคุณสมบัติที่ต้องการของอาเรย์ (นั่นคือองค์ประกอบของอาเรย์) เนื่องจากfor..in
-loop จะถูกระบุในเบราว์เซอร์ดั้งเดิมหรือหากคุณสมบัติเพิ่มเติมถูกกำหนดเป็นenumerable
.
ในECMAScript 5จะมีวิธี forEach ของอาเรย์ต้นแบบ แต่ไม่รองรับในเบราว์เซอร์รุ่นเก่า ดังนั้นเพื่อให้สามารถใช้งานได้อย่างสม่ำเสมอคุณต้องมีสภาพแวดล้อมที่รองรับ (เช่นNode.jsสำหรับ JavaScript ฝั่งเซิร์ฟเวอร์) หรือใช้ "Polyfill" Polyfill สำหรับฟังก์ชั่นนี้มีความสำคัญและทำให้อ่านรหัสได้ง่ายขึ้นจึงเป็นโพลีฟิลที่ดีที่จะรวม
for(instance in objArray)
การใช้งานไม่ถูกต้อง มันดูเรียบง่ายสำหรับฉัน แต่ฉันได้ยินว่าคุณพูดถึงวิธีการใช้งานที่ไม่ถูกต้อง?
var
คำหลักเดียว ถ้าเราใช้เซมิโคลอนก็element
จะถูกประกาศในขอบเขตทั่วโลก (หรือค่อนข้าง JSHint จะกรีดร้องที่เราก่อนที่จะถึงการผลิต)
หากคุณใช้ไลบรารีjQueryคุณสามารถใช้jQuery.each :
$.each(yourArray, function(index, value) {
// do your stuff here
});
แก้ไข:
ตามคำถามผู้ใช้ต้องการรหัสใน javascript แทน jquery ดังนั้นการแก้ไขคือ
var length = yourArray.length;
for (var i = 0; i < length; i++) {
// Do something with yourArray[i].
}
ฉันคิดว่าการย้อนกลับของลูปควรได้รับการกล่าวถึงที่นี่:
for (var i = array.length; i--; ) {
// process array[i]
}
len
ตัวแปรชั่วคราวหรือเปรียบเทียบกับarray.length
การทำซ้ำแต่ละครั้งซึ่งหนึ่งในนั้นอาจเป็นการปรับให้เหมาะสมหนึ่งนาทีarray[i]
) จากนั้นวนไปข้างหน้าจะข้ามรายการที่เลื่อนไปทางซ้ายสู่ตำแหน่งiหรือดำเนินการรายการiที่เป็น เลื่อนไปทางขวา ในแบบดั้งเดิมสำหรับลูปคุณสามารถอัปเดตiให้ชี้ไปที่รายการถัดไปที่ต้องการการประมวลผล - 1 แต่การกลับทิศทางของการวนซ้ำนั้นมักจะเป็นวิธีที่ง่ายกว่าและสวยงามกว่าforEach()
และเพื่อ for ... of
ES6นักพัฒนาบางคนใช้การย้อนกลับสำหรับการวนซ้ำโดยค่าเริ่มต้นเว้นแต่จะมีเหตุผลที่ดีที่จะส่งต่อการวนซ้ำ
แม้ว่าประสิทธิภาพจะเพิ่มขึ้นเล็กน้อย แต่ก็มีเสียงกรีดร้อง:
"ทำสิ่งนี้กับทุกรายการในรายการฉันไม่สนใจเกี่ยวกับการสั่งซื้อ!"
อย่างไรก็ตามในทางปฏิบัติที่เป็นไม่จริงเป็นตัวบ่งชี้ความน่าเชื่อถือของเจตนาเพราะมันเป็นแยกไม่ออกจากโอกาสเหล่านั้นเมื่อคุณทำดูแลเกี่ยวกับการสั่งซื้อและทำจริงๆจำเป็นต้องห่วงในสิ่งที่ตรงกันข้าม ดังนั้นในความเป็นจริงสร้างอีกจะต้องถูกต้องแสดงว่า "ไม่สนใจ" เจตนาอะไรบางอย่างที่ไม่สามารถใช้งานในภาษามากที่สุดรวมทั้ง ECMAScript ปัจจุบัน forEachUnordered()
แต่ที่อาจจะเรียกว่ายกตัวอย่างเช่น
หากคำสั่งซื้อไม่สำคัญและประสิทธิภาพเป็นสิ่งที่น่ากังวล (ในวงด้านในสุดของเกมหรืออนิเมชั่นเอนจิ้น) ดังนั้นอาจเป็นเรื่องที่ยอมรับได้ที่จะใช้ reverse for loop เป็นรูปแบบไปสู่ เพียงจำไว้ว่าการเห็นการย้อนกลับของลูปในโค้ดที่มีอยู่ไม่ได้แปลว่าคำสั่งนั้นไม่เกี่ยวข้อง!
โดยทั่วไปแล้วสำหรับรหัสระดับที่สูงขึ้นซึ่งความชัดเจนและความปลอดภัยเป็นเรื่องที่น่ากังวลมากขึ้นผมขอแนะนำให้ใช้Array::forEach
เป็นรูปแบบเริ่มต้นของคุณในการวนลูป (แม้ว่าวันนี้ฉันชอบที่จะใช้for..of
) เหตุผลที่ชอบforEach
มากกว่าการวนกลับคือ:
for
และwhile
ลูป)จากนั้นเมื่อคุณเห็นการย้อนกลับของการวนซ้ำในรหัสของคุณนั่นเป็นคำใบ้ว่ามันถูกย้อนกลับด้วยเหตุผลที่ดี (อาจเป็นหนึ่งในเหตุผลที่อธิบายไว้ข้างต้น) และการมองไปข้างหน้าแบบดั้งเดิมสำหรับลูปอาจบ่งบอกว่าสามารถขยับได้
(หากการอภิปรายเกี่ยวกับเจตนาไม่สมเหตุสมผลกับคุณคุณและรหัสของคุณอาจได้รับประโยชน์จากการดูการบรรยายของ Crockford เกี่ยวกับรูปแบบการเขียนโปรแกรมและสมองของคุณ )
มีการถกเถียงกันว่าจะดีกว่าfor..of
หรือไม่forEach()
:
สำหรับการรองรับเบราว์เซอร์สูงสุดfor..of
ต้องใช้ตัวเติมสำหรับตัววนซ้ำทำให้แอปของคุณช้าลงเล็กน้อยในการดำเนินการและดาวน์โหลดให้ใหญ่ขึ้นเล็กน้อย
ด้วยเหตุผลนั้น (และเพื่อส่งเสริมการใช้map
และfilter
) คำแนะนำแบบฟรอนต์เอนด์บางคำสั่งห้ามfor..of
อย่างสมบูรณ์!
แต่ข้อกังวลข้างต้นไม่สามารถใช้ได้กับแอปพลิเคชัน Node.js ซึ่งfor..of
ขณะนี้ได้รับการสนับสนุนเป็นอย่างดี
และยิ่งawait
ไม่ทำงานforEach()
ภายใน การใช้for..of
เป็นรูปแบบที่ชัดเจนที่สุดในกรณีนี้
โดยส่วนตัวแล้วฉันมักจะใช้สิ่งที่อ่านง่ายที่สุดเว้นแต่ว่าประสิทธิภาพหรือการย่อจะกลายเป็นปัญหาใหญ่ ดังนั้นวันนี้ผมชอบที่จะใช้for..of
แทนforEach()
แต่ฉันมักจะใช้map
หรือfilter
หรือfind
หรือsome
ใช้บังคับเมื่อ (เพื่อประโยชน์ของเพื่อนร่วมงานของฉันฉันไม่ค่อยได้ใช้reduce
)
for (var i = 0; i < array.length; i++) { ... } // Forwards
for (var i = array.length; i--; ) { ... } // Reverse
คุณจะสังเกตเห็นว่าi--
เป็นประโยคกลาง (ที่เรามักจะเห็นการเปรียบเทียบ) และประโยคสุดท้ายว่างเปล่า (ที่เรามักจะเห็นi++
) นั่นหมายความว่าi--
จะใช้เป็นเงื่อนไขสำหรับการต่อเนื่อง สิ่งสำคัญคือมันจะถูกดำเนินการและตรวจสอบก่อนการทำซ้ำแต่ละครั้ง
มันจะเริ่มarray.length
ได้อย่างไรโดยไม่ระเบิด
เพราะi--
วิ่งก่อนที่จะซ้ำกันในการย้ำแรกที่เราจะจริงจะเข้าถึงรายการที่array.length - 1
ที่หลีกเลี่ยงปัญหาใด ๆ กับอาร์เรย์ออกจากขอบเขต undefined
รายการ
ทำไมมันไม่หยุดย้ำก่อนดัชนี 0?
ลูปจะหยุดการวนซ้ำเมื่อเงื่อนไขi--
ประเมินค่า falsey (เมื่อให้ผลเป็น 0)
เคล็ดลับคือไม่เหมือน--i
กันตัวi--
ดำเนินการต่อท้ายจะลดลงi
แต่ให้ค่าก่อนที่จะลดลง คอนโซลของคุณสามารถสาธิตสิ่งนี้:
> var i = 5; [i, i--, i];
[5, 5, 4]
ดังนั้นในการทำซ้ำครั้งสุดท้ายฉันเป็น1ก่อนหน้านี้และการi--
แสดงออกเปลี่ยนเป็น0แต่จริง ๆ แล้วให้ผลตอบแทน1 (ความจริง) และเงื่อนไขผ่าน ทวนถัดไปi--
เปลี่ยนแปลงฉันจะ-1แต่อัตราผลตอบแทน0 (falsey) ทำให้เกิดการดำเนินการทันทีหล่นออกมาจากด้านล่างของวง
ในการส่งต่อแบบดั้งเดิมสำหรับวงi++
และ++i
สามารถใช้แทนกันได้ (ตามที่ Douglas Crockford ชี้ให้เห็น) อย่างไรก็ตามใน reverse for loop เนื่องจากการลดลงของเรายังเป็นการแสดงออกถึงเงื่อนไขของเราเราต้องยึดติดกับi--
ถ้าเราต้องการประมวลผลรายการที่ดัชนี 0
บางคนชอบวาดลูกศรเล็ก ๆ ในfor
วงย้อนกลับและจบด้วยพริบตา:
for (var i = array.length; i --> 0 ;) {
เครดิตไปที่ WYL เพื่อแสดงให้ฉันเห็นถึงประโยชน์และความน่ากลัวของการย้อนกลับของการวนซ้ำ
ภาษาC- style บางภาษาใช้foreach
ในการวนลูปผ่านการแจกแจง ใน JavaScript สามารถทำได้ด้วยfor..in
โครงสร้างลูป :
var index,
value;
for (index in obj) {
value = obj[index];
}
มีการจับ for..in
จะวนซ้ำแต่ละสมาชิกของวัตถุที่นับจำนวนได้และสมาชิกบนต้นแบบของมัน เพื่อหลีกเลี่ยงการอ่านค่าที่สืบทอดมาจากต้นแบบของวัตถุเพียงตรวจสอบว่าทรัพย์สินเป็นของวัตถุ:
for (i in obj) {
if (obj.hasOwnProperty(i)) {
//do stuff
}
}
นอกจากนี้ECMAScript 5ได้เพิ่มforEach
วิธีการArray.prototype
ที่สามารถใช้ในการแจกแจงอาร์เรย์โดยใช้ calback (polyfill อยู่ในเอกสารเพื่อให้คุณยังสามารถใช้สำหรับเบราว์เซอร์รุ่นเก่า):
arr.forEach(function (val, index, theArray) {
//do stuff
});
สิ่งสำคัญคือให้ทราบว่าArray.prototype.forEach
จะไม่แตกเมื่อโทรกลับfalse
มา jQueryและUnderscore.jsจัดเตรียมรูปแบบของตนเองeach
เพื่อให้ลูปที่สามารถลัดวงจรได้
each
วิธีการที่อนุญาตให้return false
ใช้เพื่อแยกวงออก แต่ด้วยforEach
ตัวเลือกนี้ไม่ใช่ตัวเลือก สามารถใช้ค่าสถานะภายนอกได้ (เช่นif (flag) return;
แต่จะป้องกันเฉพาะส่วนที่เหลือของฟังก์ชันฟังก์ชันเท่านั้นที่forEach
จะดำเนินการต่อไป แต่จะยังคงวนซ้ำทั้งชุดทั้งหมดต่อไป
หากคุณต้องการวนซ้ำอาร์เรย์ให้ใช้วงสามส่วนfor
มาตรฐาน
for (var i = 0; i < myArray.length; i++) {
var arrayItem = myArray[i];
}
คุณสามารถรับประสิทธิภาพการเพิ่มประสิทธิภาพได้โดยการแคชmyArray.length
หรือวนซ้ำไปข้างหลัง
length
ที่ยังจะสร้างตัวแปรทั่วโลกใหม่ที่เรียกว่า ;)
,
หลังจากที่มอบหมายไม่ได้แนะนำโลกใหม่เพื่อให้ข้อเสนอแนะของคุณเป็นเพียงที่ดี ! ฉันสับสนสิ่งนี้สำหรับปัญหาที่แตกต่าง: การใช้=
หลังจากที่ได้รับมอบหมายจะสร้างโลกใหม่
var i, length, arrayItem;
ก่อนวงเพื่อหลีกเลี่ยงความเข้าใจผิดนี้
ฉันรู้ว่านี่เป็นโพสต์เก่าและมีคำตอบที่ดีมากมายแล้ว สำหรับผมเล็ก ๆ น้อย ๆ ความสมบูรณ์มากขึ้นคิดฉันโยนในอีกคนหนึ่งใช้AngularJS แน่นอนว่าจะมีผลเฉพาะถ้าคุณใช้แองกูลาร์เท่านั้นแน่นอนว่าฉันต้องการจะใช้มัน
angular.forEach
ใช้เวลา 2 ข้อโต้แย้งและข้อโต้แย้งที่สามตัวเลือก อาร์กิวเมนต์แรกคือวัตถุ (อาร์เรย์) เพื่อวนซ้ำอาร์กิวเมนต์ที่สองคือฟังก์ชันตัววนซ้ำและอาร์กิวเมนต์ที่สามที่เป็นตัวเลือกคือบริบทของวัตถุ
มีวิธีการที่แตกต่างกันในการใช้ forEach แต่ละวงของมุม ที่ง่ายที่สุดและอาจใช้มากที่สุดคือ
var temp = [1, 2, 3];
angular.forEach(temp, function(item) {
//item will be each element in the array
//do something
});
อีกวิธีหนึ่งที่มีประโยชน์สำหรับการคัดลอกไอเท็มจากหนึ่งอาเรย์หนึ่งไปอีกอันคือ
var temp = [1, 2, 3];
var temp2 = [];
angular.forEach(temp, function(item) {
this.push(item); //"this" refers to the array passed into the optional third parameter so, in this case, temp2.
}, temp2);
แม้ว่าคุณไม่จำเป็นต้องทำเช่นนั้นคุณสามารถทำสิ่งต่อไปนี้และเทียบเท่ากับตัวอย่างก่อนหน้านี้:
angular.forEach(temp, function(item) {
temp2.push(item);
});
ขณะนี้มีข้อดีและข้อเสียของการใช้angular.forEach
ฟังก์ชั่นซึ่งตรงข้ามกับวงวนิลาที่ปรุงแต่งfor
แล้ว
ข้อดี
angular.forEach
จะใช้ ES5 forEach loop ตอนนี้ผมจะได้รับจากการทดลองในส่วนข้อเสียเป็นลูป forEach มีมากช้ากว่าสำหรับลูป ฉันพูดถึงเรื่องนี้ในฐานะมืออาชีพเพราะมันดีที่จะสอดคล้องและเป็นมาตรฐานพิจารณาลูปซ้อนกัน 2 ต่อไปนี้ซึ่งทำสิ่งเดียวกัน สมมติว่าเรามี 2 อาร์เรย์ของวัตถุและแต่ละวัตถุมีอาร์เรย์ของผลลัพธ์แต่ละอันมีคุณสมบัติค่าที่เป็นสตริง (หรืออะไรก็ตาม) และสมมติว่าเราจำเป็นต้องทำซ้ำผลลัพธ์แต่ละรายการและหากพวกมันเท่ากันให้ดำเนินการบางอย่าง:
angular.forEach(obj1.results, function(result1) {
angular.forEach(obj2.results, function(result2) {
if (result1.Value === result2.Value) {
//do something
}
});
});
//exact same with a for loop
for (var i = 0; i < obj1.results.length; i++) {
for (var j = 0; j < obj2.results.length; j++) {
if (obj1.results[i].Value === obj2.results[j].Value) {
//do something
}
}
}
จริงอยู่ที่นี่เป็นตัวอย่างสมมุติฐานที่ง่ายมาก แต่ฉันเขียนทริปเปิลฝังตัวสำหรับลูปโดยใช้วิธีที่สองและมันยากมากที่จะอ่านและเขียนสำหรับเรื่องนั้น
จุดด้อย
angular.forEach
และพื้นเมืองforEach
สำหรับเรื่องที่มีทั้งมากช้ากว่าปกติfor
ห่วง .... เกี่ยวกับ90% ช้า ดังนั้นสำหรับชุดข้อมูลขนาดใหญ่ควรยึดติดกับการfor
วนซ้ำดั้งเดิมcontinue
ได้รับการสนับสนุนจริงโดย " อุบัติเหตุ " เพื่อดำเนินการต่อในการที่angular.forEach
คุณง่ายใส่return;
คำสั่งในฟังก์ชั่นangular.forEach(array, function(item) { if (someConditionIsTrue) return; });
ที่จะทำให้มันออกไปจากฟังก์ชั่นสำหรับการทำซ้ำนั้น นี่ก็เป็นเพราะความจริงที่ว่าชาวพื้นเมืองforEach
ไม่สนับสนุนการหยุดพักหรือดำเนินการต่อเช่นกันฉันแน่ใจว่ามีข้อดีและข้อเสียอื่น ๆ อีกมากมายและโปรดเพิ่มสิ่งที่คุณเห็นว่าเหมาะสม ฉันรู้สึกว่าบรรทัดล่างถ้าคุณต้องการประสิทธิภาพติดกับfor
ห่วงพื้นเมืองสำหรับความต้องการวนรอบของคุณ แต่ถ้าชุดข้อมูลของคุณมีขนาดเล็กลงและประสิทธิภาพบางอย่างก็โอเคที่จะยอมแพ้เพื่อแลกกับการอ่านและเขียนได้ดังนั้นโดยรวมแล้วการโยนangular.forEach
เด็กเลวคนนั้น
หากคุณไม่สนใจล้างอาเรย์
var x;
while(x = y.pop()){
alert(x); //do something
}
x
จะมีค่าสุดท้ายของy
และมันจะถูกลบออกจากอาร์เรย์ นอกจากนี้คุณยังสามารถใช้ที่จะให้และลบรายการแรกจากshift()
y
[1, 2, undefined, 3]
มันไม่ทำงานหากเกิดขึ้นจะมีอาร์เรย์ที่เบาบางเช่น
[1, 2, 0, 3]
หรือ[true, true, false, true]
forEachการดำเนินงาน ( เห็นใน jsFiddle ):
function forEach(list,callback) {
var length = list.length;
for (var n = 0; n < length; n++) {
callback.call(list[n]);
}
}
var myArray = ['hello','world'];
forEach(
myArray,
function(){
alert(this); // do something
}
);
อาจเป็นfor(i = 0; i < array.length; i++)
ลูปไม่ใช่ตัวเลือกที่ดีที่สุด ทำไม? หากคุณมีสิ่งนี้:
var array = new Array();
array[1] = "Hello";
array[7] = "World";
array[11] = "!";
วิธีการที่จะเรียกจากไปarray[0]
array[2]
ก่อนอื่นสิ่งนี้จะอ้างอิงตัวแปรแรกที่คุณไม่มีแม้กระทั่งอันดับที่สองคุณจะไม่มีตัวแปรในอาร์เรย์และอันดับที่สามจะทำให้รหัสโดดเด่นยิ่งขึ้น ดูที่นี่เป็นสิ่งที่ฉันใช้:
for(var i in array){
var el = array[i];
//If you want 'i' to be INT just put parseInt(i)
//Do something with el
}
และถ้าคุณต้องการให้มันเป็นฟังก์ชั่นคุณสามารถทำได้:
function foreach(array, call){
for(var i in array){
call(array[i]);
}
}
ถ้าคุณต้องการที่จะทำลายตรรกะน้อยมาก:
function foreach(array, call){
for(var i in array){
if(call(array[i]) == false){
break;
}
}
}
ตัวอย่าง:
foreach(array, function(el){
if(el != "!"){
console.log(el);
} else {
console.log(el+"!!");
}
});
มันกลับมา:
//Hello
//World
//!!!
มีการนำไปใช้งานสามแบบforeach
ในjQueryดังนี้
var a = [3,2];
$(a).each(function(){console.log(this.valueOf())}); //Method 1
$.each(a, function(){console.log(this.valueOf())}); //Method 2
$.each($(a), function(){console.log(this.valueOf())}); //Method 3
ณ วันที่ ECMAScript 6:
list = [0, 1, 2, 3]
for (let obj of list) {
console.log(obj)
}
ในกรณีที่of
หลีกเลี่ยงความแปลกประหลาดที่เกี่ยวข้องกับin
และทำให้มันทำงานเหมือนfor
วนของภาษาอื่น ๆ และlet
ผูกi
ภายในวงเมื่อเทียบกับภายในฟังก์ชั่น
วงเล็บปีกกา ( {}
) สามารถละเว้นได้เมื่อมีเพียงหนึ่งคำสั่ง (เช่นในตัวอย่างด้านบน)
วิธีง่ายในตอนนี้จะเป็นการใช้ห้องสมุด underscore.js มันมีเครื่องมือที่มีประโยชน์มากมายเช่นeach
และจะมอบหมายงานให้กับเจ้าของภาษาโดยอัตโนมัติforEach
หากมี
ตัวอย่างของCodePenว่าทำงานอย่างไร:
var arr = ["elemA", "elemB", "elemC"];
_.each(arr, function(elem, index, ar)
{
...
});
Array.prototype.forEach()
เอกสารสำหรับพื้นเมืองfor each (variable in object)
เลิกใช้แล้วในส่วนของมาตรฐาน ECMA-357 ( EAX )for (variable of object)
เป็นส่วนหนึ่งของข้อเสนอ Harmony (ECMAScript 6)มีไม่ใด ๆfor each
วงในพื้นเมืองJavaScript คุณสามารถใช้ไลบรารีเพื่อรับฟังก์ชั่นนี้ (ฉันแนะนำUnderscore.js ) ใช้การfor
วนรอบแบบง่าย ๆ
for (var instance in objects) {
...
}
อย่างไรก็ตามโปรดทราบว่าอาจมีเหตุผลที่จะใช้การfor
วนซ้ำที่ง่ายกว่าเดิม(ดูคำถาม Stack Overflow เหตุใดการใช้“ for … in” กับการวนซ้ำของอาร์เรย์จึงเป็นความคิดที่ไม่ดี? )
var instance;
for (var i=0; i < objects.length; i++) {
var instance = objects[i];
...
}
นี่เป็นตัววนซ้ำสำหรับรายการที่ไม่กระจายซึ่งดัชนีเริ่มต้นที่ 0 ซึ่งเป็นสถานการณ์ทั่วไปเมื่อจัดการกับ document.getElementsByTagName หรือ document.querySelectorAll)
function each( fn, data ) {
if(typeof fn == 'string')
eval('fn = function(data, i){' + fn + '}');
for(var i=0, L=this.length; i < L; i++)
fn.call( this[i], data, i );
return this;
}
Array.prototype.each = each;
ตัวอย่างการใช้งาน:
ตัวอย่างที่ 1
var arr = [];
[1, 2, 3].each( function(a){ a.push( this * this}, arr);
arr = [1, 4, 9]
ตัวอย่างที่ 2
each.call(document.getElementsByTagName('p'), "this.className = data;",'blue');
แต่ละแท็กจะได้รับ class="blue"
ตัวอย่างที่ 3
each.call(document.getElementsByTagName('p'),
"if( i % 2 == 0) this.className = data;",
'red'
);
แท็ก p อื่น ๆ จะได้รับclass="red"
>
ตัวอย่าง # 4
each.call(document.querySelectorAll('p.blue'),
function(newClass, i) {
if( i < 20 )
this.className = newClass;
}, 'green'
);
และในที่สุดแท็กสีน้ำเงิน 20 อันแรกก็เปลี่ยนเป็นสีเขียว
ข้อควรระวังเมื่อใช้สตริงเป็นฟังก์ชั่น: ฟังก์ชั่นนี้ถูกสร้างขึ้นนอกบริบทและควรใช้เฉพาะเมื่อคุณมีการกำหนดขอบเขตที่แน่นอน มิฉะนั้นดีกว่าที่จะผ่านฟังก์ชั่นที่กำหนดขอบเขตง่าย
มีวิธีการวนซ้ำในอาร์เรย์ใน JavaScript ดังนี้:
สำหรับ - เป็นหนึ่งที่พบมากที่สุด รหัสเต็มบล็อกสำหรับการวนซ้ำ
var languages = ["Java", "JavaScript", "C#", "Python"];
var i, len, text;
for (i = 0, len = languages.length, text = ""; i < len; i++) {
text += languages[i] + "<br>";
}
document.getElementById("example").innerHTML = text;
<p id="example"></p>
ในขณะที่ - วงในขณะที่เงื่อนไขผ่าน ดูเหมือนว่าจะเป็นวงที่เร็วที่สุด
var text = "";
var i = 0;
while (i < 10) {
text += i + ") something<br>";
i++;
}
document.getElementById("example").innerHTML = text;
<p id="example"></p>
do / while - ยังวนลูปผ่านบล็อกของรหัสในขณะที่เงื่อนไขเป็นจริงจะทำงานอย่างน้อยหนึ่งครั้ง
var text = ""
var i = 0;
do {
text += i + ") something <br>";
i++;
}
while (i < 10);
document.getElementById("example").innerHTML = text;
<p id="example"></p>
ลูปการทำงาน - forEach
, map
, filter
ยังreduce
(ห่วงพวกเขาผ่านการทำงาน แต่พวกเขาจะใช้ถ้าคุณต้องการที่จะทำบางสิ่งบางอย่างกับอาร์เรย์ของคุณ ฯลฯ
// For example, in this case we loop through the number and double them up using the map function
var numbers = [65, 44, 12, 4];
document.getElementById("example").innerHTML = numbers.map(function(num){return num * 2});
<p id="example"></p>
สำหรับข้อมูลเพิ่มเติมและตัวอย่างเกี่ยวกับการเขียนโปรแกรมการทำงานบนอาร์เรย์ดูที่โพสต์บล็อกโปรแกรมการทำงานใน JavaScript: แผนที่กรองและลด
forEach
ไม่ใช่ลูป "ใช้งานได้" เนื่องจากไม่ได้ส่งคืนใหม่Array
(อันที่จริงแล้วมันไม่ส่งคืนอะไรเลย) แต่มันวนซ้ำ
ECMAScript 5 (เวอร์ชันบน JavaScript) เพื่อทำงานกับอาร์เรย์:
forEach - วนซ้ำทุกรายการในอาร์เรย์และทำทุกอย่างที่คุณต้องการกับแต่ละรายการ
['C', 'D', 'E'].forEach(function(element, index) {
console.log(element + " is #" + (index+1) + " in the musical scale");
});
// Output
// C is the #1 in musical scale
// D is the #2 in musical scale
// E is the #3 in musical scale
ในกรณีที่มีความสนใจในการดำเนินการเกี่ยวกับอาร์เรย์โดยใช้คุณสมบัติ inbuilt
แผนที่ - มันจะสร้างอาร์เรย์ใหม่ที่มีผลลัพธ์ของฟังก์ชั่นการโทรกลับ วิธีนี้เป็นวิธีที่ดีที่จะใช้เมื่อคุณต้องการจัดรูปแบบองค์ประกอบของอาร์เรย์
// Let's upper case the items in the array
['bob', 'joe', 'jen'].map(function(elem) {
return elem.toUpperCase();
});
// Output: ['BOB', 'JOE', 'JEN']
ลด - ตามชื่อบอกว่ามันจะลดอาร์เรย์เป็นค่าเดียวโดยการเรียกฟังก์ชั่นที่กำหนดผ่านในองค์ประกอบปัจจุบันและผลของการดำเนินการก่อนหน้านี้
[1,2,3,4].reduce(function(previous, current) {
return previous + current;
});
// Output: 10
// 1st iteration: previous=1, current=2 => result=3
// 2nd iteration: previous=3, current=3 => result=6
// 3rd iteration: previous=6, current=4 => result=10
ทุก - ส่งกลับจริงหรือเท็จถ้าองค์ประกอบทั้งหมดในอาร์เรย์ผ่านการทดสอบในฟังก์ชั่นการโทรกลับ
// Check if everybody has 18 years old of more.
var ages = [30, 43, 18, 5];
ages.every(function(elem) {
return elem >= 18;
});
// Output: false
ตัวกรอง - คล้ายกันมากกับทุกตัวยกเว้นตัวกรองนั้นจะส่งกลับอาร์เรย์พร้อมองค์ประกอบที่ส่งกลับค่าจริงไปยังฟังก์ชันที่กำหนด
// Finding the even numbers
[1,2,3,4,5,6].filter(function(elem){
return (elem % 2 == 0)
});
// Output: [2,4,6]
ไม่มีความสามารถที่จะทำลาย inbuilt forEach
ในเป็น หากต้องการขัดจังหวะการทำงานให้ใช้สิ่งArray#some
ต่อไปนี้:
[1,2,3].some(function(number) {
return number === 1;
});
ใช้งานได้เนื่องจากsome
คืนค่าเป็นจริงทันทีที่มีการเรียกกลับใด ๆ ดำเนินการตามลำดับอาร์เรย์ส่งคืนจริงประมวลผลส่วนที่เหลือลัดวงจร
คำตอบเดิม
ดูที่ Array prototype สำหรับบางคน
ฉันยังต้องการเพิ่มสิ่งนี้เป็นองค์ประกอบของการวนกลับและคำตอบข้างต้นสำหรับคนที่ต้องการไวยากรณ์นี้ด้วย
var foo = [object,object,object];
for (var i = foo.length, item; item = foo[--i];) {
console.log(item);
}
ข้อดี:
ประโยชน์สำหรับสิ่งนี้: คุณมีการอ้างอิงอยู่แล้วในแบบแรกที่ไม่จำเป็นต้องประกาศในภายหลังด้วยบรรทัดอื่น มันมีประโยชน์เมื่อวนลูปอาร์เรย์อาร์เรย์วัตถุ
จุดด้อย:
สิ่งนี้จะแตกเมื่อใดก็ตามที่การอ้างอิงเป็นเท็จ - เท็จ (ไม่ได้กำหนด ฯลฯ ) มันสามารถใช้เป็นข้อได้เปรียบแม้ว่า อย่างไรก็ตามมันจะทำให้อ่านยากขึ้นเล็กน้อย และขึ้นอยู่กับเบราว์เซอร์มันสามารถ "ไม่" ปรับให้ทำงานเร็วกว่าเดิม
วิธีการใช้ jQuery $.map
:
var data = [1, 2, 3, 4, 5, 6, 7];
var newData = $.map(data, function(element) {
if (element % 2 == 0) {
return element;
}
});
// newData = [2, 4, 6];
การใช้ลูปกับ ECMAScript 6 การทำลายล้างและตัวดำเนินการสเปรด
การทำลายล้างและการใช้งานของตัวดำเนินการสเปรดได้พิสูจน์แล้วว่าค่อนข้างมีประโยชน์สำหรับผู้มาใหม่ไปยัง ECMAScript 6 ว่าเป็นมนุษย์ที่อ่านได้ / สวยงามมากขึ้นแม้ว่าทหารผ่านศึกจาวาสคริปต์บางคนอาจคิดว่ามันยุ่งเหยิง รุ่นน้องหรือคนอื่น ๆ อาจพบว่ามีประโยชน์
ตัวอย่างต่อไปนี้จะใช้
for...of
คำสั่งและ.forEach
วิธีการตัวอย่าง 6, 7, 8 และสามารถใช้กับลูปการทำงานใด ๆ เช่น
.map
,.filter
,.reduce
,.sort
, ,.every
.some
สำหรับข้อมูลเพิ่มเติมเกี่ยวกับวิธีการเหล่านี้ตรวจสอบวัตถุอาร์เรย์
ตัวอย่างที่ 1:for...of
วนรอบปกติ- ไม่มีลูกเล่นที่นี่
let arrSimple = ['a', 'b', 'c'];
for (let letter of arrSimple) {
console.log(letter);
}
ตัวอย่างที่ 2:แบ่งคำเป็นอักขระ
let arrFruits = ['apple', 'orange', 'banana'];
for (let [firstLetter, ...restOfTheWord] of arrFruits) {
// Create a shallow copy using the spread operator
let [lastLetter] = [...restOfTheWord].reverse();
console.log(firstLetter, lastLetter, restOfTheWord);
}
ตัวอย่างที่ 3:วนรอบด้วยkey
และvalue
// let arrSimple = ['a', 'b', 'c'];
// Instead of keeping an index in `i` as per example `for(let i = 0 ; i<arrSimple.length;i++)`
// this example will use a multi-dimensional array of the following format type:
// `arrWithIndex: [number, string][]`
let arrWithIndex = [
[0, 'a'],
[1, 'b'],
[2, 'c'],
];
// Same thing can be achieved using `.map` method
// let arrWithIndex = arrSimple.map((i, idx) => [idx, i]);
// Same thing can be achieved using `Object.entries`
// NOTE: `Object.entries` method doesn't work on Internet Explorer unless it's polyfilled
// let arrWithIndex = Object.entries(arrSimple);
for (let [key, value] of arrWithIndex) {
console.log(key, value);
}
ตัวอย่างที่ 4: รับคุณสมบัติของวัตถุในบรรทัด
let arrWithObjects = [{
name: 'Jon',
age: 32
},
{
name: 'Elise',
age: 33
}
];
for (let { name, age: aliasForAge } of arrWithObjects) {
console.log(name, aliasForAge);
}
ตัวอย่างที่ 5: รับคุณสมบัติวัตถุลึกของสิ่งที่คุณต้องการ
let arrWithObjectsWithArr = [{
name: 'Jon',
age: 32,
tags: ['driver', 'chef', 'jogger']
},
{
name: 'Elise',
age: 33,
tags: ['best chef', 'singer', 'dancer']
}
];
for (let { name, tags: [firstItemFromTags, ...restOfTags] } of arrWithObjectsWithArr) {
console.log(name, firstItemFromTags, restOfTags);
}
ตัวอย่างที่ 6:เป็นตัวอย่าง 3 ที่ใช้กับ.forEach
let arrWithIndex = [
[0, 'a'],
[1, 'b'],
[2, 'c'],
];
// Not to be confused here, `forEachIndex` is the real index
// `mappedIndex` was created by "another user", so you can't really trust it
arrWithIndex.forEach(([mappedIndex, item], forEachIndex) => {
console.log(forEachIndex, mappedIndex, item);
});
ตัวอย่างที่ 7:คือตัวอย่างที่ 4 ที่ใช้กับ.forEach
let arrWithObjects = [{
name: 'Jon',
age: 32
},
{
name: 'Elise',
age: 33
}
];
// NOTE: Destructuring objects while using shorthand functions
// are required to be surrounded by parentheses
arrWithObjects.forEach( ({ name, age: aliasForAge }) => {
console.log(name, aliasForAge)
});
ตัวอย่างที่ 8:คือตัวอย่าง 5 ที่ใช้กับ.forEach
let arrWithObjectsWithArr = [{
name: 'Jon',
age: 32,
tags: ['driver', 'chef', 'jogger']
},
{
name: 'Elise',
age: 33,
tags: ['best chef', 'singer', 'dancer']
}
];
arrWithObjectsWithArr.forEach(({
name,
tags: [firstItemFromTags, ...restOfTags]
}) => {
console.log(name, firstItemFromTags, restOfTags);
});
วิธีที่ใกล้เคียงที่สุดกับความคิดของคุณคือการใช้Array.forEach()
ซึ่งยอมรับฟังก์ชั่นการปิดซึ่งจะถูกดำเนินการสำหรับแต่ละองค์ประกอบของอาร์เรย์
myArray.forEach(
(item) => {
// Do something
console.log(item);
}
);
อีกวิธีหนึ่งที่ใช้งานได้คือการใช้Array.map()
ซึ่งทำงานในลักษณะเดียวกัน แต่ก็ต้องใช้ค่าทั้งหมดที่คุณส่งคืนและส่งกลับไปยังอาร์เรย์ใหม่ (โดยการจับคู่แต่ละองค์ประกอบกับองค์ประกอบใหม่) เช่นนี้:
var myArray = [1, 2, 3];
myArray = myArray.map(
(item) => {
return item + 1;
}
);
console.log(myArray); // [2, 3, 4]
map
ไม่ได้ทำการเปลี่ยนแปลงองค์ประกอบของอาเรย์เพราะมันจะส่งคืนอาเรย์ใหม่โดยที่ไอเท็มของอันใหม่นั้นเป็นผลมาจากการใช้ฟังก์ชั่นกับรายการของอาเรย์เก่า
คุณสามารถโทรหาแต่ละคนดังนี้:
forEach
จะวนซ้ำในอาร์เรย์ที่คุณให้ไว้และสำหรับการวนซ้ำแต่ละครั้งจะมีค่าelement
ที่เก็บค่าการทำซ้ำนั้น หากคุณต้องการดัชนีคุณสามารถรับดัชนีปัจจุบันโดยส่งผ่านi
พารามิเตอร์ตัวที่สองในฟังก์ชั่นการโทรกลับสำหรับ forEach
Foreach นั้นเป็นฟังก์ชั่นการสั่งซื้อสูงซึ่งใช้ฟังก์ชั่นอื่นเป็นพารามิเตอร์
let theArray= [1,3,2];
theArray.forEach((element) => {
// Use the element of the array
console.log(element)
}
เอาท์พุท:
1
3
2
นอกจากนี้คุณยังสามารถวนซ้ำแถวลำดับดังนี้:
for (let i=0; i<theArray.length; i++) {
console.log(i); // i will have the value of each index
}
หากคุณต้องการวนลูปผ่านอาร์เรย์ของวัตถุด้วยฟังก์ชั่นลูกศร:
let arr = [{name:'john', age:50}, {name:'clark', age:19}, {name:'mohan', age:26}];
arr.forEach((person)=>{
console.log('I am ' + person.name + ' and I am ' + person.age + ' old');
})
ไวยากรณ์แลมบ์ดามักจะไม่ทำงานใน Internet Explorer 10 หรือต่ำกว่า
ฉันมักจะใช้
[].forEach.call(arrayName,function(value,index){
console.log("value of the looped element" + value);
console.log("index of the looped element" + index);
});
หากคุณเป็นแฟน jQuery และมีไฟล์ jQuery ทำงานอยู่คุณควรกลับตำแหน่งของดัชนีและพารามิเตอร์ค่า
$("#ul>li").each(function(**index, value**){
console.log("value of the looped element" + value);
console.log("index of the looped element" + index);
});
หากคุณมีชุดมากมายคุณควรใช้iterators
เพื่อเพิ่มประสิทธิภาพ Iterators เป็นทรัพย์สินของคอลเลกชัน JavaScript บางอย่าง (เช่นMap
, Set
, String
, Array
) แม้กระทั่งfor..of
ใช้iterator
ภายใต้ประทุน
Iterators ปรับปรุงประสิทธิภาพโดยให้คุณใช้รายการในรายการทีละรายการราวกับว่าเป็นสตรีม สิ่งที่ทำให้ตัวทำซ้ำพิเศษคือวิธีที่มันไปเก็บสะสม ลูปอื่นต้องโหลดคอลเลกชันทั้งหมดขึ้นด้านหน้าเพื่อวนซ้ำในขณะที่ตัววนซ้ำต้องรู้ตำแหน่งปัจจุบันในคอลเลกชันเท่านั้น
คุณเข้าถึงรายการปัจจุบันโดยการเรียกใช้next
วิธีการตัววนซ้ำ วิธีถัดไปจะคืนค่าvalue
รายการปัจจุบันและ a boolean
เพื่อระบุว่าเมื่อใดที่คุณถึงจุดสิ้นสุดของการรวบรวม ต่อไปนี้เป็นตัวอย่างของการสร้างตัววนซ้ำจากอาร์เรย์
แปลงอาเรย์ปกติของคุณเป็นตัววนซ้ำโดยใช้values()
วิธีดังนี้:
const myArr = [2,3,4]
let it = myArr.values();
console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());
คุณสามารถเปลี่ยนอาเรย์ปกติของคุณเป็นตัววนซ้ำโดยใช้Symbol.iterator
ดังนี้:
const myArr = [2,3,4]
let it = myArr[Symbol.iterator]();
console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());
คุณยังสามารถเปลี่ยนรูปแบบปกติของคุณarray
เป็นiterator
แบบนี้ได้:
let myArr = [8, 10, 12];
function makeIterator(array) {
var nextIndex = 0;
return {
next: function() {
return nextIndex < array.length ?
{value: array[nextIndex++], done: false} :
{done: true};
}
};
};
var it = makeIterator(myArr);
console.log(it.next().value); // {value: 8, done: false}
console.log(it.next().value); // {value: 10, done: false}
console.log(it.next().value); // {value: 12, done: false}
console.log(it.next().value); // {value: undefined, done: true}
หมายเหตุ :
iterable
ค่าเริ่มต้น ใช้for..in
ในกรณีนั้นเพราะแทนที่จะใช้ค่าจะทำงานกับคีย์หากคุณต้องการใช้forEach()
มันจะมีลักษณะเหมือน -
theArray.forEach ( element => {
console.log(element);
});
หากคุณต้องการใช้for()
มันจะมีลักษณะเหมือน -
for(let idx = 0; idx < theArray.length; idx++){
let element = theArray[idx];
console.log(element);
}
ตามคุณลักษณะที่อัพเดตใหม่ ECMAScript 6 (ES6) และ ECMAScript 2015 คุณสามารถใช้ตัวเลือกต่อไปนี้พร้อมลูป:
สำหรับลูป
for(var i = 0; i < 5; i++){
console.log(i);
}
// Output: 0,1,2,3,4
สำหรับ ... ในลูป
let obj = {"a":1, "b":2}
for(let k in obj){
console.log(k)
}
// Output: a,b
Array.forEach ()
let array = [1,2,3,4]
array.forEach((x) => {
console.log(x);
})
// Output: 1,2,3,4
สำหรับ ... จากลูป
let array = [1,2,3,4]
for(let x of array){
console.log(x);
}
// Output: 1,2,3,4
ในขณะที่ลูป
let x = 0
while(x < 5){
console.log(x)
x++
}
// Output: 1,2,3,4
ทำ ... ในขณะที่ลูป
let x = 0
do{
console.log(x)
x++
}while(x < 5)
// Output: 1,2,3,4
วันนี้ (2019-12-18) ฉันทดสอบmacOS v10.13.6 (High Sierra) ของฉันบน Chrome v 79.0, Safari v13.0.4 และ Firefox v71.0 (64 บิต) - ข้อสรุปเกี่ยวกับการเพิ่มประสิทธิภาพ (และการเพิ่มประสิทธิภาพแบบไมโครซึ่ง มักจะไม่คุ้มค่าที่จะแนะนำให้รู้จักกับรหัสเพราะผลประโยชน์มีขนาดเล็ก แต่ความซับซ้อนของรหัสจะเพิ่มขึ้น)
ดูเหมือนว่าดั้งเดิมfor i
( Aa ) เป็นตัวเลือกที่ดีในการเขียนโค้ดอย่างรวดเร็วบนเบราว์เซอร์ทั้งหมด
โซลูชันอื่น ๆ เช่นfor-of
( โฆษณา ) ทั้งหมดในกลุ่มC. ... มักจะช้ากว่าAa 2 - 10 (และอื่น ๆ ) แต่สำหรับอาร์เรย์ขนาดเล็กก็สามารถใช้งานได้ - เพื่อประโยชน์ในการเพิ่มความชัดเจนของรหัส
ลูปที่มีความยาวของอาร์เรย์เก็บไว้ในn
( Ab, Bb, Be ) บางครั้งก็เร็วกว่า แต่ก็ไม่ใช่ คอมไพเลอร์อาจตรวจจับสถานการณ์นี้โดยอัตโนมัติและแนะนำแคช ความแตกต่างระหว่างความเร็วเวอร์ชันแคชและไม่มีที่เก็บไว้ชั่วคราว ( Aa, บา, Bd ) ประมาณ ~ 1% เพื่อให้ดูเหมือนว่าแนะนำn
เป็นไมโครเพิ่มประสิทธิภาพ
i--
เช่นการแก้ปัญหาที่ห่วงเริ่มต้นจากองค์ประกอบอาร์เรย์ที่ผ่านมา ( Ac, BC ) มักจะ ~ 30% ช้ากว่าการแก้ปัญหาไปข้างหน้า - อาจเป็นเหตุผลทางของหน่วยความจำแคช CPU ทำงาน - อ่านหน่วยความจำไปข้างหน้าเป็นที่เหมาะสมมากขึ้นสำหรับการแคช CPU) ไม่แนะนำให้ใช้วิธีการแก้ปัญหาดังกล่าว
ในการทดสอบเราคำนวณผลรวมขององค์ประกอบอาร์เรย์ ฉันทำการทดสอบสำหรับอาร์เรย์ขนาดเล็ก (10 องค์ประกอบ) และอาร์เรย์ขนาดใหญ่ (องค์ประกอบ 1M) และแบ่งออกเป็นสามกลุ่ม:
for
การทดสอบwhile
การทดสอบข้ามผลลัพธ์ของเบราว์เซอร์
ผลลัพธ์สำหรับเบราว์เซอร์ที่ทดสอบทั้งหมด
อาเรย์กับ 10 องค์ประกอบ
ผลลัพธ์สำหรับ Chrome คุณสามารถดำเนินการทดสอบบนเครื่องของคุณที่นี่
อาร์เรย์ที่มีองค์ประกอบ 1,000,000 รายการ
ผลลัพธ์สำหรับ Chrome คุณสามารถทำการทดสอบบนเครื่องของคุณได้ที่นี่
เมื่อวนซ้ำแถวลำดับเรามักต้องการบรรลุหนึ่งในเป้าหมายต่อไปนี้:
เราต้องการวนซ้ำอาร์เรย์และสร้างอาร์เรย์ใหม่:
Array.prototype.map
เราต้องการวนซ้ำอาร์เรย์และไม่สร้างอาร์เรย์ใหม่:
Array.prototype.forEach
for..of
ห่วง
ใน JavaScript มีหลายวิธีในการบรรลุเป้าหมายทั้งสองนี้ อย่างไรก็ตามบางคนสะดวกกว่าคนอื่น ด้านล่างนี้คุณสามารถค้นหาวิธีที่ใช้กันทั่วไป (IMO ที่สะดวกที่สุด) เพื่อทำซ้ำอาร์เรย์ใน JavaScript
Map
map()
เป็นฟังก์ชั่นที่ตั้งอยู่Array.prototype
ซึ่งสามารถแปลงทุกองค์ประกอบของอาเรย์แล้วส่งกลับอาร์เรย์ใหม่ map()
ใช้เป็นอาร์กิวเมนต์สำหรับฟังก์ชันเรียกกลับและทำงานในลักษณะดังต่อไปนี้:
let arr = [1, 2, 3, 4, 5];
let newArr = arr.map((element, index, array) => {
return element * 2;
})
console.log(arr);
console.log(newArr);
การเรียกกลับที่เราได้ส่งผ่านไปmap()
เป็นอาร์กิวเมนต์จะถูกดำเนินการสำหรับทุกองค์ประกอบ จากนั้นอาร์เรย์จะได้รับคืนซึ่งมีความยาวเท่ากับอาร์เรย์เดิม ในองค์ประกอบอาร์เรย์ใหม่นี้จะถูกแปลงโดยฟังก์ชั่นการโทรกลับผ่านในฐานะที่เป็นอาร์กิวเมนต์map()
ในองค์ประกอบอาร์เรย์ใหม่นี้จะถูกเปลี่ยนโดยฟังก์ชันการเรียกกลับผ่านเป็นอาร์กิวเมนต์ไปยัง
ความแตกต่างที่ชัดเจนระหว่างmap
และกลไกลูปอื่นเช่นforEach
และfor..of
ลูปคือการmap
ส่งคืนอาเรย์ใหม่และปล่อยให้อาเรย์เก่ายังคงอยู่ (ยกเว้นถ้าคุณจัดการกับมันอย่างชัดเจนด้วยความคิดเช่นsplice
)
นอกจากนี้โปรดทราบว่าการmap
เรียกกลับของฟังก์ชันให้หมายเลขดัชนีของการวนซ้ำปัจจุบันเป็นอาร์กิวเมนต์ที่สอง นอกจากนี้อาร์กิวเมนต์ที่สามให้อาเรย์ที่map
ถูกเรียก? บางครั้งคุณสมบัติเหล่านี้อาจมีประโยชน์มาก
forEach
forEach
เป็นฟังก์ชั่นซึ่งตั้งอยู่Array.prototype
ที่ใช้ฟังก์ชั่นการโทรกลับเป็นข้อโต้แย้ง จากนั้นจะเรียกใช้ฟังก์ชันการเรียกกลับนี้สำหรับทุกองค์ประกอบในอาร์เรย์ ตรงกันข้ามกับmap()
ฟังก์ชั่นฟังก์ชั่น forEach จะไม่ส่งคืนอะไร ( undefined
) ตัวอย่างเช่น:
let arr = [1, 2, 3, 4, 5];
arr.forEach((element, index, array) => {
console.log(element * 2);
if (index === 4) {
console.log(array)
}
// index, and oldArray are provided as 2nd and 3th argument by the callback
})
console.log(arr);
เช่นเดียวกับmap
ฟังก์ชั่นการforEach
โทรกลับให้หมายเลขดัชนีของการวนซ้ำปัจจุบันเป็นอาร์กิวเมนต์ที่สอง อาร์กิวเมนต์ที่สามจัดเตรียมอาร์เรย์ที่forEach
เรียกว่าหรือไม่
for..of
การfor..of
วนซ้ำวนรอบองค์ประกอบของอาร์เรย์ทุกครั้ง (หรือวัตถุที่ทำซ้ำได้อื่น ๆ ) มันทำงานในลักษณะดังต่อไปนี้:
let arr = [1, 2, 3, 4, 5];
for(let element of arr) {
console.log(element * 2);
}
ในตัวอย่างข้างต้นelement
หมายถึงองค์ประกอบอาร์เรย์และarr
เป็นอาร์เรย์ที่เราต้องการวนรอบ สังเกตว่าชื่อelement
นั้นเป็นโดยพลการและเราสามารถเลือกชื่ออื่น ๆ เช่น 'el' หรือชื่ออื่นที่มีความหมายมากกว่านี้ได้
อย่าสับสนระหว่างfor..in
ลูปกับfor..of
ลูป for..in
จะวนซ้ำผ่านคุณสมบัติที่นับได้ทั้งหมดของอาเรย์ในขณะที่for..of
ลูปจะวนลูปผ่านองค์ประกอบอาเรย์เท่านั้น ตัวอย่างเช่น:
let arr = [1, 2, 3, 4, 5];
arr.foo = 'foo';
for(let element of arr) {
console.log(element);
}
for(let element in arr) {
console.log(element);
}
forEach
for
ตามที่ระบุไว้ใน c # มันเป็นความแตกต่างกันเล็กน้อยและที่ฉันสับสน :)