Array.apply 实际在做什么 [英] What is Array.apply actually doing

查看:29
本文介绍了Array.apply 实际在做什么的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

阅读这个SO问题后,我对 Array.apply 实际在做什么仍然有点困惑.考虑以下片段:

After reading this SO Question, I'm still a little confused as to what Array.apply is actually doing. Consider the following snippet:

new Array(5).map(function(){
  return new Array(5);
});

我希望这会初始化一个包含 5 个未定义条目的数组,然后映射它们创建一个 5x5 的二​​维数组);

I expect this to init an array with 5 undefined entries, then map over them creating a two dimensional array of 5x5);

相反,我只是获取数组,就好像它从未被映射过一样:

Instead I just get the array as if it was never mapped over:

[undefined, undefined, undefined, undefined, undefined]

当我在 Array.apply 调用中包装对数组的构造函数调用,然后映射它时,它按预期工作:

When I wrap the constructor call to array in an Array.apply call, then map over that, it works as expected:

Array.apply(null, new Array(5)).map(function(){
  return new Array(5);
});

导致;

[[undefined, undefined, undefined, undefined, undefined],
 [undefined, undefined, undefined, undefined, undefined],
 [undefined, undefined, undefined, undefined, undefined],
 [undefined, undefined, undefined, undefined, undefined],
 [undefined, undefined, undefined, undefined, undefined]];

怎么了?Array.apply 只是调用 new Array() 或 Array.prototype.constructor 的另一种方式吗?是否有任何其他情况这将是有利的?另外,为什么我的第一个方法没有在我发送它的地图上找到?

What's the deal? Is Array.apply just another way of calling new Array(), or Array.prototype.constructor? Are there any other situations where this would be advantageous? Also, why didn't my first approach pick up on the map I was sending it through?

谢谢!-尼尔

推荐答案

好问题!

Array 构造函数(with 可以在没有 new 的情况下使用),当传递超过 1 个参数时,创建一个包含作为其元素传入的参数的数组.所以你可以这样做:

The Array constructor function (with can be used without new), when passed more than 1 argument, creates an array containing the arguments passed in as its elements. So you can do this:

Array(1, 2, 3); // => [1, 2, 3]

您可能知道,Function.prototype.apply 允许您以数组的形式为函数提供参数.所以调用 Array.apply(它只是从 Function 的原型中继承了它的 .apply() 方法;任何作为 Function 实例的函数都允许你这样做),将功能等同于上面的代码:

As you probably know, Function.prototype.apply allows you to provide arguments to a function in the form of an array. So calling Array.apply (which just inherits its .apply() method from Function's prototype; any function that is an instance of Function would allows you to do this), which will be functionality equivalent to the code above:

Array.apply(null, [1, 2, 3]); // => [1, 2, 3]

现在,这就是事情有点混乱的原因.Array.prototype.map 方法被指定为专门处理稀疏数组.稀疏数组的长度"大于实际插入的元素数.例如:

Now, here's why things are a bit confusing. The Array.prototype.map method is spec'd in such a way that it deals with sparse arrays specially. A sparse array is one that has a "length" that is greater than the number of elements that have actually been inserted. For example:

var arr = [];
arr[0] = 'foo';
arr[5] = 'bar';

上面构造的数组的 length 属性为 6,因为它在索引 0 处有一个元素,在索引 5 处有一个元素.然而,因为从来没有元素插入在这些索引之间,如果你在上面调用 map 你会看到映射函数没有被应用到缺失的元素上:

The array constructed above will have a length property of 6, because it has an element at index 0 and one at index 5. However, since no elements were ever inserted between those indices, if you call map on it you'll see that the mapping function does not get applied to the missing elements:

// This should throw, right? Since elements 1 through 4 are undefined?
var lengths = arr.map(function(s) { return s.length; });

// Nope!
lengths; // => [3, , , , , 3]

为什么我们会在您使用 new Array(5) 的示例中看到这种行为?你猜对了:因为数组构造函数,当给定一个参数时,会创建一个具有指定长度的稀疏数组.

And why are we seeing this behavior in your example with new Array(5)? You guessed it: because the array constructor, when given a single argument, creates a sparse array with the specified length.

所以这里的问题是,虽然 map(以及 Array.prototype 上的其他方法,例如 forEach)对通过跳过缺失值来处理稀疏数组,Function.prototype.apply 方法没有任何此类特殊行为.

So the issue here is that while map (and other methods on Array.prototype, such as forEach) behaves specially with respect to sparse arrays by skipping over the missing values, the Function.prototype.apply method does not have any such special behavior.

这篇关于Array.apply 实际在做什么的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆