在不是数组的可迭代对象上调用 Array.map 是否有效?
Is it valid to call Array.map on an iterable that is not an array?
这篇文章: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,但找不到那里允许这样的用法。
然而,文章的作者强调:
Even though map() is a function of Array.prototype, it works on any array-like iterable.
这样的使用是否像他声称的那样有效?如果是这样,其他 Array.prototype.*
函数是否也是这种情况,例如 filter
、slice
,甚至 pop
、push
、其他函数?
是的,通常有效。但是我同意你的观点:
Array.from(elements).map(element => /*..*/);
// Or even
Array.from(elements, element => /*...*/);
干净多了。
Unless it is somewhere explicitely stated that this is allowed
是的,它在the specification:
The map
function is intentionally generic; it does not require that its this value be an Array
object. Therefore it can be transferred to other kinds of objects for use as a method.
Array.prototype
上的大多数方法都有该说明。不能那样用的就没有那个备注。
因此,是否要使用它纯粹是风格问题。不同的人会对它是否 good/bad/indifferent 风格有不同的看法。
旁注:如果你打算那样使用 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);
这篇文章: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,但找不到那里允许这样的用法。
然而,文章的作者强调:
Even though map() is a function of Array.prototype, it works on any array-like iterable.
这样的使用是否像他声称的那样有效?如果是这样,其他 Array.prototype.*
函数是否也是这种情况,例如 filter
、slice
,甚至 pop
、push
、其他函数?
是的,通常有效。但是我同意你的观点:
Array.from(elements).map(element => /*..*/);
// Or even
Array.from(elements, element => /*...*/);
干净多了。
Unless it is somewhere explicitely stated that this is allowed
是的,它在the specification:
The
map
function is intentionally generic; it does not require that its this value be anArray
object. Therefore it can be transferred to other kinds of objects for use as a method.
Array.prototype
上的大多数方法都有该说明。不能那样用的就没有那个备注。
因此,是否要使用它纯粹是风格问题。不同的人会对它是否 good/bad/indifferent 风格有不同的看法。
旁注:如果你打算那样使用 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);