首页 > 解决方案 > 在不是数组的可迭代对象上调用 Array.map 是否有效?

问题描述

这篇文章:使用 filter()、map() 和箭头函数遍历 DOM提倡这样的使用,Array.map这在我看来很奇怪。更具体地说,文章的作者声称以下代码是有效的,并且实际上比替代代码更好Array.from(elements).map(...)

var elements = document.getElementsByClassName("bgflag");
BgFlags = Array.prototype.map.call(elements,
        element =>
        ({
            height: element.offsetTop,
            bgsrc: element.dataset.bgsrc,
            bgcolor: element.dataset.bgcolor,
            size: element.dataset.size,
            name: element.id,
            image: parseInt(element.dataset.image)
        })
    );

这对我未经训练的眼睛来说似乎是最可疑的。我们正在呼吁Array.prototype.map一些不是Array. 除非在某处明确声明这是允许的,否则这对我来说就像是未定义的行为。我快速浏览了相关的 MDN 文档,但找不到那里允许这样的用法。

然而,文章的作者强调:

即使 map() 是 Array.prototype 的一个函数,它也适用于任何类似数组的可迭代对象。

正如他所声称的那样,这种使用是否有效?如果是这样,其他Array.prototype.*功能是否也是如此,例如filter, slice, 甚至pop, push, 其他?

标签: javascriptarraysjavascript-objectsarray.prototype.map

解决方案


除非在某处明确说明这是允许的

是的,它在规范中:

map功能是故意通用的;它不要求它的 this 值是一个Array对象。因此,它可以转移到其他类型的对象中用作方法。

大多数方法Array.prototype都有这个注释。不能这样使用的没有那个注释。

因此,您是否要使用它纯粹是风格问题。不同的人会对风格的好/坏/冷漠有不同的看法。


旁注:如果你打算使用map这种方式,而不是每次都写那个手写体,给自己一个捷径:

const map = Function.prototype.call.bind(Array.prototype.map);

然后像这样使用它:

const result = map(arrayLike, e => /*...*/);

现场示例:

const map = Function.prototype.call.bind(Array.prototype.map);

const arrayLike = {
  0: "zero",
  1: "one",
  2: "two",
  length: 3
};
const result = map(arrayLike, e => e.toUpperCase());
console.log(result);


推荐阅读