เพื่อตอบคำถามเดิมคุณใช้งานfor/in
ไม่ถูกต้อง ในรหัสของคุณkey
คือดัชนี ดังนั้นเพื่อให้ได้ค่าจากหลอกอาร์เรย์ที่คุณจะต้องทำและจะได้รับประจำตัวประชาชนของคุณควรจะทำlist[key]
list[key].id
แต่คุณไม่ควรทำสิ่งนี้for/in
ในตอนแรก
สรุป (เพิ่มในธันวาคม 2018)
ห้ามใช้for/in
เพื่อทำซ้ำ nodeList หรือ HTMLCollection เหตุผลในการหลีกเลี่ยงดังอธิบายไว้ด้านล่าง
ทุกรุ่นล่าสุดของเบราว์เซอร์ที่ทันสมัย (Safari, Firefox, Chrome, EDGE) ทุกการสนับสนุนfor/of
การทำซ้ำในรายการ DOM ดังกล่าวหรือnodeList
HTMLCollection
นี่คือตัวอย่าง:
var list = document.getElementsByClassName("events");
for (let item of list) {
console.log(item.id);
}
หากต้องการรวมเบราว์เซอร์รุ่นเก่า (รวมถึงสิ่งต่างๆเช่น IE) สิ่งนี้จะทำงานได้ทุกที่:
var list= document.getElementsByClassName("events");
for (var i = 0; i < list.length; i++) {
console.log(list[i].id); //second console output
}
คำอธิบายว่าทำไมคุณไม่ควรใช้ for/in
for/in
มีความหมายสำหรับการวนซ้ำคุณสมบัติของวัตถุ นั่นหมายความว่ามันจะส่งคืนคุณสมบัติที่วนซ้ำได้ของวัตถุ แม้ว่ามันอาจจะใช้งานได้กับอาเรย์ (การส่งคืนองค์ประกอบอาเรย์หรือองค์ประกอบอาเรย์หลอก) แต่ก็สามารถส่งคืนคุณสมบัติอื่น ๆ ของวัตถุที่ไม่ใช่สิ่งที่คุณคาดหวังจากองค์ประกอบแบบอาเรย์ และเดาว่าอะไรHTMLCollection
หรือnodeList
วัตถุใดที่สามารถมีคุณสมบัติอื่นที่จะถูกส่งคืนพร้อมการfor/in
วนซ้ำ ฉันเพิ่งลองมันใน Chrome และวนซ้ำในแบบที่คุณทำซ้ำมันจะเรียกคืนรายการในรายการ (ดัชนี 0, 1, 2, ฯลฯ ... ) แต่จะดึงlength
และitem
คุณสมบัติ การfor/in
ทำซ้ำจะไม่ทำงานกับ HTMLCollection
ดูhttp://jsfiddle.net/jfriend00/FzZ2H/สำหรับเหตุผลที่คุณไม่สามารถย้ำ HTMLCollection for/in
กับ
ใน Firefox for/in
การทำซ้ำของคุณจะส่งคืนรายการเหล่านี้ (คุณสมบัติที่ทำซ้ำได้ทั้งหมดของวัตถุ):
0
1
2
item
namedItem
@@iterator
length
หวังว่าตอนนี้คุณสามารถดูว่าทำไมคุณต้องการที่จะใช้for (var i = 0; i < list.length; i++)
แทนดังนั้นคุณก็จะได้รับ0
, 1
และ2
ในการทำซ้ำของคุณ
การติดตามด้านล่างนี้เป็นวิวัฒนาการของวิธีที่เบราว์เซอร์มีวิวัฒนาการตลอดช่วงเวลาระหว่าง 2558-2561 ซึ่งจะทำให้คุณสามารถทำซ้ำ ไม่จำเป็นต้องใช้สิ่งเหล่านี้ในเบราว์เซอร์สมัยใหม่เนื่องจากคุณสามารถใช้ตัวเลือกที่อธิบายไว้ข้างต้น
อัพเดทสำหรับ ES6 ในปี 2558
เพิ่มใน ES6 คือArray.from()
จะแปลงโครงสร้างคล้ายอาร์เรย์เป็นอาร์เรย์จริง ที่อนุญาตให้หนึ่งแจกแจงรายการโดยตรงเช่นนี้
"use strict";
Array.from(document.getElementsByClassName("events")).forEach(function(item) {
console.log(item.id);
});
สาธิตการทำงาน (ใน Firefox, Chrome และ Edge ณ เดือนเมษายน 2559): https://jsfiddle.net/jfriend00/8ar4xn2s/
อัปเดตสำหรับ ES6 ในปี 2559
ตอนนี้คุณสามารถใช้ ES6 สำหรับ / ของการสร้างกับNodeList
และHTMLCollection
โดยเพียงแค่เพิ่มสิ่งนี้ในรหัสของคุณ:
NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
HTMLCollection.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
จากนั้นคุณสามารถ:
var list = document.getElementsByClassName("events");
for (var item of list) {
console.log(item.id);
}
สามารถใช้งานได้กับ Chrome, Firefox และ Edge รุ่นปัจจุบัน สิ่งนี้ทำงานได้เพราะมันแนบ Array iterator กับทั้ง NodeList และ HTMLCollection prototypes ดังนั้นเมื่อสำหรับ / ของ iterates เหล่านั้นมันจะใช้ Arer iterator เพื่อย้ำพวกมัน
การสาธิตการทำงาน: http://jsfiddle.net/jfriend00/joy06u4e/
การอัปเดตครั้งที่สองสำหรับ ES6 ในเดือนธันวาคม 2559
ตั้งแต่เดือนธันวาคม 2559 Symbol.iterator
การสนับสนุนได้ติดตั้งไว้ใน Chrome v54 และ Firefox v50 ดังนั้นโค้ดด้านล่างจึงสามารถใช้งานได้ด้วยตัวเอง มันยังไม่ได้ติดตั้งไว้สำหรับ Edge
var list = document.getElementsByClassName("events");
for (let item of list) {
console.log(item.id);
}
สาธิตการทำงาน (ใน Chrome และ Firefox): http://jsfiddle.net/jfriend00/3ddpz8sp/
การอัพเดทครั้งที่สามสำหรับ ES6 ในเดือนธันวาคม 2017
ณ ธันวาคม 2017, ความสามารถนี้ทำงานในขอบ 41.16299.15.0 สำหรับnodeList
ในขณะที่document.querySelectorAll()
แต่ไม่ได้เป็นHTMLCollection
เช่นเดียวกับในdocument.getElementsByClassName()
ดังนั้นคุณต้องกำหนด iterator HTMLCollection
ที่จะใช้ในขอบด้วยตนเอง มันเป็นความลึกลับโดยรวมว่าทำไมพวกเขาถึงต้องแก้ไขคอลเล็กชันประเภทหนึ่ง แต่ไม่ใช่ประเภทอื่น แต่อย่างน้อยคุณสามารถใช้ผลลัพธ์ของการdocument.querySelectorAll()
ใช้for/of
ไวยากรณ์ES6 ในเวอร์ชันปัจจุบันของ Edge ได้ทันที
ผมได้ปรับปรุงยังด้านบน jsFiddle จึงทดสอบทั้งสองHTMLCollection
และnodeList
แยกจากกันและจับเอาท์พุทใน jsFiddle เอง
การอัพเดทครั้งที่สี่สำหรับ ES6 ในเดือนมีนาคม 2018
ต่อ mesqueeeb, Symbol.iterator
การสนับสนุนได้รับการสร้างขึ้นในซาฟารีเกินไปดังนั้นคุณจึงสามารถใช้for (let item of list)
อย่างใดอย่างหนึ่งหรือdocument.getElementsByClassName()
document.querySelectorAll()
การอัพเดทครั้งที่ห้าสำหรับ ES6 ในเดือนเมษายน 2018
เห็นได้ชัดว่าการสนับสนุนการทำซ้ำHTMLCollection
ด้วยfor/of
จะมาถึง Edge 18 ในฤดูใบไม้ร่วง 2018
การอัพเดทครั้งที่หกสำหรับ ES6 ในเดือนพฤศจิกายน 2018
ฉันสามารถยืนยันได้ด้วย Microsoft Edge v18 (ซึ่งรวมอยู่ใน Fall 2018 Windows Update) ตอนนี้คุณสามารถทำซ้ำทั้ง HTMLCollection และ NodeList ด้วย for / of in Edge
ดังนั้นตอนนี้เบราว์เซอร์ที่ทันสมัยทั้งหมดมีการสนับสนุนเนทิฟสำหรับfor/of
การวนซ้ำของทั้งวัตถุ HTMLCollection และ NodeList