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

zei*_*oon 7 javascript arrays map

我有以下一些代码来选择一些div并在它们上面添加一个click处理程序

var tiles = document.getElementsByClassName("tile");

tiles.map(function(tile, i){
    tile.addEventListener("click", function(e){
        console.log("click!");
    });
});
Run Code Online (Sandbox Code Playgroud)

这会引发错误,因为map未定义,即使tiles是一个数组.如果我这样做一个数组,那么map工作正常:

var a = [1, 2, 3, 4];
a.map(/*whatever*/);
Run Code Online (Sandbox Code Playgroud)

解决方法是将贴图附加到贴图,如下所示:

tiles.map = Array.prototype.map;
Run Code Online (Sandbox Code Playgroud)

这很好用.我的问题是为什么没有tiles定义地图呢?它不是真正的阵列吗?

小智 18

对,它不是一个真正的数组.这是一个"阵列式".

不重视maptiles.做就是了

Array.prototype.map.call(tiles, function...)
Run Code Online (Sandbox Code Playgroud)

有人可能会建议

Array.prototype.slice.call(tiles).map(function...
Run Code Online (Sandbox Code Playgroud)

哪种归结为同一件事.有些人喜欢写作

[].slice.call(tiles).map(function...
Run Code Online (Sandbox Code Playgroud)

这节省了一些按键.

当然,既然你不是真的map用来返回一个数组,你可以用老式的方式循环:

for (var i = 0; i < tiles.length; i++) {
    tiles[i].addEventListener("click", function(e){
        console.log("click!");
    });
}
Run Code Online (Sandbox Code Playgroud)

另见MDN的解释.虽然这个讨论NodeList,但同样的原则适用于HTMLCollection,这就是getElementsByClassName回报.

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

[...tiles]
Array.from(tiles)
Run Code Online (Sandbox Code Playgroud)