关于javascript:`document.getElementsByClassName`的结果没有定义像`map`这样的数组方法,即使它是一个数组

Result of `document.getElementsByClassName` doesn't have array methods like `map` defined, even though it is an array

我具有以下代码来选择一些div并在其上添加点击处理程序

1
2
3
4
5
6
7
var tiles = document.getElementsByClassName("tile");

tiles.map(function(tile, i){
    tile.addEventListener("click", function(e){
        console.log("click!");
    });
});

这将引发错误,因为即使tile是数组,也未定义map
如果我创建这样的数组,则映射可以正常工作:

1
2
var a = [1, 2, 3, 4];
a.map(/*whatever*/);

一种解决方法是将地图附加到图块上,如下所示:

1
tiles.map = Array.prototype.map;

这很好。
我的问题是为什么tiles上没有定义地图?它不是数组吗?


对,它实际上不是数组。这是"类似数组的"。

不要将map附加到tiles。只要做

1
Array.prototype.map.call(tiles, function...)

有人可能会建议

1
Array.prototype.slice.call(tiles).map(function...

归结为同一件事。有些人喜欢写

1
[].slice.call(tiles).map(function...

可以节省一些击键。

当然,由于您并没有真正使用map返回数组,因此可以采用老式的方式循环:

1
2
3
4
5
for (var i = 0; i < tiles.length; i++) {
    tiles[i].addEventListener("click", function(e){
        console.log("click!");
    });
}

另请参见MDN中的说明。尽管本文讨论了NodeList,但相同的原理也适用于HTMLCollection,这是getElementsByClassName返回的结果。

在ES6中,我们有一些更简单的方法可以将tiles转换为数组,包括

1
2
[...tiles]
Array.from(tiles)