在不是数组的迭代上调用Array.map是否有效?

时间:2018-06-05 17:27:02

标签: javascript arrays javascript-objects array.prototype.map

这篇文章:Traversing the DOM with filter(), map(), and arrow functions提倡使用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。除非明确说明这是允许的,否则这对我来说就像是未定义的行为。我快速浏览了the relevant MDN documentation,但无法在那里找到这样的用法。

然而,该文章的作者强调:

  

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

这样的使用是否有效,正如他声称的那样?如果是这样,其他Array.prototype.*函数也是如此,例如filterslice,甚至poppush,其他?

2 个答案:

答案 0 :(得分:4)

  

除非明确说明这是允许的,否则

它是,the specification

  

map函数是故意通用的;它不要求它的值为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);




答案 1 :(得分:1)

是的,通常有效。不过我同意你的意见:

Array.from(elements).map(element => /*..*/);
// Or even
Array.from(elements, element => /*...*/);

更干净。