เพื่อตอบคำถามเดิมคุณใช้งานfor/inไม่ถูกต้อง ในรหัสของคุณkeyคือดัชนี ดังนั้นเพื่อให้ได้ค่าจากหลอกอาร์เรย์ที่คุณจะต้องทำและจะได้รับประจำตัวประชาชนของคุณควรจะทำlist[key] list[key].idแต่คุณไม่ควรทำสิ่งนี้for/inในตอนแรก
สรุป (เพิ่มในธันวาคม 2018)
ห้ามใช้for/inเพื่อทำซ้ำ nodeList หรือ HTMLCollection เหตุผลในการหลีกเลี่ยงดังอธิบายไว้ด้านล่าง
ทุกรุ่นล่าสุดของเบราว์เซอร์ที่ทันสมัย (Safari, Firefox, Chrome, EDGE) ทุกการสนับสนุนfor/ofการทำซ้ำในรายการ DOM ดังกล่าวหรือnodeListHTMLCollection
นี่คือตัวอย่าง:
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