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

查看:240
本文介绍了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调用中包装对array的构造函数调用,然后在其上映射时,它可以按预期工作:

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是调用新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构造函数(可以在不使用new的情况下使用),当传递多个参数时,将创建一个数组,其中包含作为元素传递的参数.因此,您可以执行以下操作:

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)的示例中看到这种现象?您猜对了:因为数组构造函数在给定单个参数时会创建具有指定长度的 sparse 数组.

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天全站免登陆