335 javascript dom
我正在尝试设置所有元素的get id HTMLCollectionOf
.我写了以下代码:
var list = document.getElementsByClassName("events");
console.log(list[0].id);
for (key in list) {
console.log(key.id);
}
Run Code Online (Sandbox Code Playgroud)
但我在控制台中得到以下输出:
event1
undefined
Run Code Online (Sandbox Code Playgroud)
这不是我的预期.为什么第二个控制台输出undefined
但第一个控制台输出是event1
?
jfr*_*d00 715
摘要(2018年12月添加)
不要for/in
用于迭代nodeList或HTMLCollection.避免它的原因如下所述.
所有最近的现代浏览器版本(Safari浏览器,火狐,Chrome,边缘)都支持key
DOM的迭代列出了这样list[key]
或list[key].id
.
这是一个例子:
var list = document.getElementsByClassName("events");
for (let item of list) {
console.log(item.id);
}
Run Code Online (Sandbox Code Playgroud)
要包含旧浏览器(包括IE之类的东西),这将适用于所有地方:
var list= document.getElementsByClassName("events");
for (var i = 0; i < list.length; i++) {
console.log(list[i].id); //second console output
}
Run Code Online (Sandbox Code Playgroud)
解释为什么你不应该使用 for/in
for/in
用于迭代对象的属性.这意味着它将返回对象的所有可迭代属性.虽然它似乎适用于数组(返回数组元素或伪数组元素),但它也可以返回对象的其他属性,这些属性不是您期望的类数组元素.并且,猜猜是什么,一个for/of
或一个nodeList
对象都可以具有将通过HTMLCollection
迭代返回的其他属性.我只是在Chrome中尝试过这个并按照你迭代它的方式迭代它将检索列表中的项目(索引0,1,2等等),但也会检索for/in
和for/in
属性.该HTMLCollection
迭代根本不会对的HTMLCollection工作.
请参阅http://jsfiddle.net/jfriend00/FzZ2H/,了解为什么你不能迭代HTMLCollection nodeList
.
在Firefox中,您的for/in
迭代将返回这些项(对象的所有可迭代属性):
0
1
2
item
namedItem
@@iterator
length
Run Code Online (Sandbox Code Playgroud)
希望现在你可以看到你想要使用的原因,length
以便你得到item
,for/in
并for/in
在你的迭代中.
以下是浏览器在2015-2018期间的演变过程的演变,为您提供了其他迭代方法.现在浏览器中现在都不需要这些,因为您可以使用上述选项.
2015年更新ES6
添加到ES6是for/in
将类似数组的结构转换为实际数组.这允许人们直接枚举列表,如下所示:
"use strict";
Array.from(document.getElementsByClassName("events")).forEach(function(item) {
console.log(item.id);
});
Run Code Online (Sandbox Code Playgroud)
工作演示(截至2016年4月的Firefox,Chrome和Edge):https://jsfiddle.net/jfriend00/8ar4xn2s/
2016年ES6更新
您现在可以将ES6 for/of construct与a for (var i = 0; i < list.length; i++)
和a一起使用0
,只需将其添加到您的代码中:
NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
HTMLCollection.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
Run Code Online (Sandbox Code Playgroud)
然后,你可以这样做:
var list = document.getElementsByClassName("events");
for (var item of list) {
console.log(item.id);
}
Run Code Online (Sandbox Code Playgroud)
这适用于当前版本的Chrome,Firefox和Edge.这是因为它将Array迭代器附加到NodeList和HTMLCollection原型,因此当for/of迭代它们时,它使用Array迭代器来迭代它们.
工作演示:http://jsfiddle.net/jfriend00/joy06u4e/.
2016年12月ES6的第二次更新
截至2016年12月,1
Chrome v54和Firefox v50已内置支持,因此下面的代码可单独使用.Edge尚未内置.
var list = document.getElementsByClassName("events");
for (let item of list) {
console.log(item.id);
}
Run Code Online (Sandbox Code Playgroud)
工作演示(在Chrome和Firefox中):http://jsfiddle.net/jfriend00/3ddpz8sp/
2017年12月ES6的第三次更新
截至2017年12月,此功能在Edge 41.16299.15.0中适用2
于in Array.from()
,但不适用于此类NodeList
,HTMLCollection
因此您必须手动分配迭代器以在Edge中使用它Symbol.iterator
.他们为什么要修复一种集合类型而不是另一种集合类型,这完全是个谜.但是,您现在至少可以在当前版本的Edge 中nodeList
使用ES6 document.querySelectorAll()
语法的结果.
我还更新了上面的jsFiddle,所以它分别测试HTMLCollection
和检测document.getElementsByClassName()
jsFiddle本身的输出.
ES8于2018年3月的第四次更新
每mesqueeeb,HTMLCollection
支持已经内置Safari浏览器,所以你可以使用document.querySelectorAll()
的两种for/of
或HTMLCollection
.
2018年4月ES6的第五次更新
显然,对于迭代的支持nodeList
与Symbol.iterator
将现身秋2018年边缘18.
2018年11月ES6第六次更新
我可以通过Microsoft Edge v18(包含在2018年秋季Windows Update中)确认,现在您可以使用Edge中的for/of迭代HTMLCollection和NodeList.
因此,现在所有现代浏览器都包含for (let item of list)
对HTMLCollection和NodeList对象的迭代的本机支持.
eva*_*phy 76
你不能在s或s 上使用for
/ .但是,你可以使用一些方法,只要它们并传入或作为.in
NodeList
HTMLCollection
Array.prototype
.call()
NodeList
HTMLCollection
this
因此,请考虑以下作为jfriend00 for
循环的替代方法:
var list= document.getElementsByClassName("events");
[].forEach.call(list, function(el) {
console.log(el.id);
});
Run Code Online (Sandbox Code Playgroud)
MDN上有一篇很好的文章介绍了这种技术.请注意他们对浏览器兼容性的警告:
[...]传递主机对象(如a
NodeList
)和this
本机方法(例如forEach
)不能保证在所有浏览器中都能正常工作,并且已知在某些浏览器中失败.
因此,虽然这种方法很方便,但for
循环可能是最兼容浏览器的解决方案.
更新(2014年8月30日):最终你将能够使用ES6 for
/of
!
var list = document.getElementsByClassName("events");
for (el of list)
console.log(el.id);
Run Code Online (Sandbox Code Playgroud)
最新版本的Chrome和Firefox已经支持它.
mid*_*ido 50
在ES6中,你可以做类似的事情[...collection]
,或者Array.from(collection)
,
let someCollection = document.querySelectorAll(someSelector)
[...someCollection].forEach(someFn)
//or
Array.from(collection).forEach(someFn)
Run Code Online (Sandbox Code Playgroud)
小智 14
你可以添加这两行:
HTMLCollection.prototype.forEach = Array.prototype.forEach;
NodeList.prototype.forEach = Array.prototype.forEach;
Run Code Online (Sandbox Code Playgroud)
HTMLCollection由getElementsByClassName和getElementsByTagName返回
NodeList由querySelectorAll返回
像这样你可以做一个forEach:
var selections = document.getElementsByClassName('myClass');
/* alternative :
var selections = document.querySelectorAll('.myClass');
*/
selections.forEach(function(element, i){
//do your stuffs
});
Run Code Online (Sandbox Code Playgroud)
for
如果您使用的是 IE9 或更高版本,则没有理由使用 es6 功能来逃避循环。
在 ES5 中,有两个不错的选择。首先,你可以像埃文提到Array
的forEach
那样“借用” 。
但更好的是...
Object.keys()
,它确实具有forEach
和 过滤器以自动“拥有属性”。也就是说,Object.keys
本质上相当于for... in
用 a做a HasOwnProperty
,但要平滑得多。
var eventNodes = document.getElementsByClassName("events");
Object.keys(eventNodes).forEach(function (key) {
console.log(eventNodes[key].id);
});
Run Code Online (Sandbox Code Playgroud)
小智 7
我在IE 11和Firefox 49中使用forEach时遇到了问题
我找到了这样的解决方法
Array.prototype.slice.call(document.getElementsByClassName("events")).forEach(function (key) {
console.log(key.id);
}
Run Code Online (Sandbox Code Playgroud)
自2016年3月起,在Chrome 49.0中,该版本for...of
适用于HTMLCollection
:
this.headers = this.getElementsByTagName("header");
for (var header of this.headers) {
console.log(header);
}
Run Code Online (Sandbox Code Playgroud)
请参阅此处的文档。
但是,只有在使用之前应用以下变通办法时,它才有效for...of
:
HTMLCollection.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
Run Code Online (Sandbox Code Playgroud)
同样是必要的使用for...of
有NodeList
:
NamedNodeMap.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
Run Code Online (Sandbox Code Playgroud)
我相信/希望for...of
上述解决方法很快就会起作用。未解决的问题在这里:
https://bugs.chromium.org/p/chromium/issues/detail?id=401699
更新:请参见下面的Expenzor注释:截至2016年4月,此问题已得到修复。您无需添加HTMLCollection.prototype [Symbol.iterator] = Array.prototype [Symbol.iterator]; 遍历带有... of的HTMLCollection
替代方法Array.from
是使用Array.prototype.forEach.call
每个:
Array.prototype.forEach.call(htmlCollection, i => { console.log(i) });
地图: Array.prototype.map.call(htmlCollection, i => { console.log(i) });
等等...
归档时间: |
|
查看次数: |
271422 次 |
最近记录: |