Để trả lời cho câu hỏi ban đầu, bạn đang sử dụng for/inkhông chính xác. Trong mã của bạn, keylà chỉ mục. Vì vậy, để có được giá trị từ mảng giả, bạn phải làm list[key]và để lấy id, bạn sẽ làm list[key].id. Nhưng, bạn không nên làm điều này với for/inở nơi đầu tiên.
Tóm tắt (được thêm vào tháng 12 năm 2018)
Đừng bao giờ sử dụng for/inđể lặp lại một danh sách nút hoặc HTMLCollection. Những lý do để tránh nó được mô tả dưới đây.
Tất cả các phiên bản gần đây của trình duyệt hiện đại (Safari, Firefox, Chrome, Edge) đều hỗ trợ for/oflặp trên danh sách DOM như vậy nodeListhoặc HTMLCollection.
Đây là một ví dụ:
var list = document.getElementsByClassName("events");
for (let item of list) {
console.log(item.id);
}
Để bao gồm các trình duyệt cũ hơn (bao gồm cả những thứ như IE), điều này sẽ hoạt động ở mọi nơi:
var list= document.getElementsByClassName("events");
for (var i = 0; i < list.length; i++) {
console.log(list[i].id); //second console output
}
Giải thích cho lý do tại sao bạn không nên sử dụng for/in
for/incó nghĩa là để lặp lại các thuộc tính của một đối tượng. Điều đó có nghĩa là nó sẽ trả về tất cả các thuộc tính lặp lại của một đối tượng. Mặc dù nó có vẻ hoạt động cho một mảng (trả về các phần tử mảng hoặc phần tử giả), nó cũng có thể trả về các thuộc tính khác của đối tượng không phải là những gì bạn đang mong đợi từ các phần tử giống như mảng. Và, đoán xem, một HTMLCollectionhoặc một nodeListđối tượng có thể có các thuộc tính khác sẽ được trả về bằng một for/inlần lặp. Tôi vừa thử điều này trong Chrome và lặp lại theo cách bạn đang lặp lại, nó sẽ lấy các mục trong danh sách (chỉ mục 0, 1, 2, v.v ...), nhưng cũng sẽ truy xuất các thuộc tính lengthvà item. Các for/inlặp chỉ đơn giản là sẽ không làm việc cho một HTMLCollection.
Xem http://jsfiddle.net/jfriend00/FzZ2H/ để biết lý do tại sao bạn không thể lặp lại HTMLCollection với for/in.
Trong Firefox, for/inphép lặp của bạn sẽ trả về các mục này (tất cả các thuộc tính lặp của đối tượng):
0
1
2
item
namedItem
@@iterator
length
Hy vọng rằng, bây giờ bạn có thể thấy lý do tại sao bạn muốn sử dụng for (var i = 0; i < list.length; i++)thay vì vậy bạn chỉ có được 0, 1và 2trong lần lặp của bạn.
Sau đây là một sự phát triển về cách các trình duyệt đã phát triển trong khoảng thời gian 2015-2018 cung cấp cho bạn các cách bổ sung để lặp lại. Hiện tại không cần điều này trong các trình duyệt hiện đại vì bạn có thể sử dụng các tùy chọn được mô tả ở trên.
Cập nhật cho ES6 năm 2015
Thêm vào ES6 là Array.from()nó sẽ chuyển đổi một cấu trúc giống như mảng thành một mảng thực tế. Điều đó cho phép người ta liệt kê một danh sách trực tiếp như thế này:
"use strict";
Array.from(document.getElementsByClassName("events")).forEach(function(item) {
console.log(item.id);
});
Bản demo hoạt động (trong Firefox, Chrome và Edge kể từ tháng 4 năm 2016): https://jsfiddle.net/jfriend00/8ar4xn2s/
Cập nhật cho ES6 năm 2016
Bây giờ bạn có thể sử dụng ES6 cho / của cấu trúc với a NodeListvà an HTMLCollectionbằng cách thêm mã này vào mã của bạn:
NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
HTMLCollection.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
Sau đó, bạn có thể làm:
var list = document.getElementsByClassName("events");
for (var item of list) {
console.log(item.id);
}
Điều này hoạt động trong phiên bản hiện tại của Chrome, Firefox và Edge. Điều này hoạt động vì nó gắn Array iterator vào cả hai nguyên mẫu NodeList và HTMLCollection để khi / cho lặp lại chúng, nó sử dụng iterator Array để lặp lại chúng.
Bản demo hoạt động: http://jsfiddle.net/jfriend00/joy06u4e/ .
Cập nhật lần thứ hai cho ES6 vào tháng 12 năm 2016
Kể từ tháng 12 năm 2016, Symbol.iteratorhỗ trợ đã được tích hợp sẵn cho Chrome v54 và Firefox v50 để mã bên dưới hoạt động. Nó chưa được tích hợp sẵn cho Edge.
var list = document.getElementsByClassName("events");
for (let item of list) {
console.log(item.id);
}
Bản trình diễn hoạt động (trong Chrome và Firefox): http://jsfiddle.net/jfriend00/3ddpz8sp/
Cập nhật lần thứ ba cho ES6 vào tháng 12 năm 2017
Tính đến tháng 12 năm 2017, khả năng này hoạt động trong cạnh 41.16299.15.0 cho một nodeListnhư trong document.querySelectorAll(), nhưng không phải là một HTMLCollectionnhư trong document.getElementsByClassName()vì vậy bạn phải tự gán các iterator để sử dụng nó trong Edge cho một HTMLCollection. Đó là một bí ẩn hoàn toàn tại sao họ sửa một loại bộ sưu tập, nhưng không phải loại khác. Nhưng, ít nhất bạn có thể sử dụng kết quả document.querySelectorAll()với for/ofcú pháp ES6 trong các phiên bản hiện tại của Edge.
Tôi cũng đã cập nhật jsFiddle ở trên để nó kiểm tra cả hai HTMLCollectionvà nodeListriêng biệt và nắm bắt đầu ra trong chính jsFiddle.
Cập nhật lần thứ tư cho ES6 vào tháng 3 năm 2018
Trên mỗi mesqueeeb, Symbol.iteratorhỗ trợ cũng đã được tích hợp vào Safari, vì vậy bạn có thể sử dụng for (let item of list)cho một trong hai document.getElementsByClassName()hoặc document.querySelectorAll().
Cập nhật lần thứ năm cho ES6 vào tháng 4 năm 2018
Rõ ràng, hỗ trợ cho việc lặp lại HTMLCollectionvới for/ofsẽ đến với Edge 18 vào mùa thu 2018.
Cập nhật lần thứ sáu cho ES6 vào tháng 11 năm 2018
Tôi có thể xác nhận rằng với Microsoft Edge v18 (được bao gồm trong Windows Update mùa thu 2018), giờ đây bạn có thể lặp lại cả HTMLCollection và NodeList với for / of trong Edge.
Vì vậy, bây giờ tất cả các trình duyệt hiện đại đều có hỗ trợ riêng cho việc for/oflặp lại cả hai đối tượng HTMLCollection và NodeList.