3

我在使用 javascript 数组时遇到了这种有线行为。我的目标是从另一个数组创建一个新数组。我的方法如下;

Array.prototype.constructor.apply(Array, [1,2])

它创建了一个新数组,其中包含 2 个元素 [1,2] 可以正常工作,但是当我放这样的东西时..

Array.prototype.constructor.apply(Array, [3])

那就是创建一个包含一个元素的数组,即[3] ...它创建

[undefined,undefined,undefined]

也就是说,它创建了一个包含 3 个空元素的数组!!知道为什么吗?以及如何以这种方式创建一个新的数组对象?

4

6 回答 6

9

那是因为带有一个参数的Array构造函数生成了一个包含元素n的数组。n使用更多参数,它会创建一个按顺序由这些参数组成的数组。

实际上,您的代码不是Array作为构造函数调用的:Array.prototype.constructor.apply(Array, [3])更像Array(3)new Array(3). 但是,无论有无 ,Array其行为都是相同的new

这一切都引出了一个问题,即当您可以只使用数组文字时,为什么首先要这样做。如果你试图复制一个数组,使用它的slice方法是一种简单的方法:

var a = [1, 2];
var copy = a.slice(0);
于 2013-09-26T14:33:15.463 回答
2
Array.prototype.constructor.apply(Array, [1,2])

其实应该是的Array.apply(null, [1, 2])Array.prototype.constructor === Array,当你这样做时,new Array(1, 2)你没有将它应用到Array构造函数上,而是什么都没有。

当我放类似它的东西时,Array.prototype.constructor.apply(Array, [3])它会创建一个包含 3 个空元素的数组!知道为什么吗?

这就是Array构造函数应该如何工作。当使用单个数字参数调用它时,它将创建一个新的空数组.length(你正在这样做:)new Array(3)

我的目标是从另一个数组创建一个新数组。

为此使用sliceArray 方法

[1, 2].slice();
// or, complicated, but works with array-like objects:
Array.prototype.slice.call([1, 2]);
于 2013-09-26T14:33:45.387 回答
2

Array 的第一个 ctor 参数是数组的长度,如果传递,new Array(3)例如将创建一个包含 3 个元素的数组,但所有元素都是未定义的原因。

因为您使用apply,所以 apply 的第二个参数是您传递给您应用它的方法的 arguments 数组。

这意味着,如果您应用的参数数组仅包含一个元素,则默认构造函数new Array(<numofelemnts>)将被执行。

于 2013-09-26T14:32:41.680 回答
1

Remember that func.apply(obj, [1,2]) is the same as obj.func(1,2). And new Array(3) has the same result you gave above - [undefined,undefined,undefined]. Blame it on the spec, but that's how it works. You have to pass more than one argument in order to have them populate the array.

于 2013-09-26T14:35:32.760 回答
0

Mozilla's MDN has a good description on why this is happening, but here's the short of it:

The Array object has two constructors.

In your first version, you're providing 2 arguments, which the Array object understands as "Create an Array with the specified values."

In your second version, you're providing 1 argument, which the Array object understands as "Create an empty array with space to hold the number specified in the argument."

So if you want an array with one object, I'd recommend bypassing the constructor.apply syntax and use something a little more readable (i.e. var array = [3];)

于 2013-09-26T14:35:08.727 回答
0

您只需要在原始数组上使用 concat 或 slice 即可。您不需要为原型调用而烦恼,因为它是为创建arguments列表的副本而保留的,以便将其转换为数组:

var new_array_copy = existing_array.slice(0)

arguments我正在谈论的功能:

function a_function_with_some_arguments(/* arguments */) {
    // Convert the special arguments list into an array
    var args = Array.prototype.slice.call(arguments, 0);

    // Returns a reference to the new copy of the arguments list.
    return args;
}
于 2013-09-26T14:31:10.410 回答