简体   繁体   中英

Weird Javascript Array.prototype.constructor.apply behaviour

I am having this wired behaviour with javascript array. My objective is the create a new array form another array. My approach is following;

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

and it creates a new array with 2 element in them [1,2] that works fine but when i put something like this..

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

that is to create a array with one element in it ie [3]... it creates

[undefined,undefined,undefined]

that is it creates an array with 3 empty elements!! Any idea why? and how i can create a new array object this way??

That's because the Array constructor with one argument, n , produces an array with n elements. With more arguments, it creates an array consisting of those arguments in order.

Actually your code is not calling Array as a constructor: Array.prototype.constructor.apply(Array, [3]) is more like Array(3) than new Array(3) . However, Array behaves the same with and without new .

This all begs the question of why you're doing this in the first place when you could just use an array literal. If you're trying to copy an array, using its slice method is a simple way:

var a = [1, 2];
var copy = a.slice(0);

The first ctor parameter of Array is length of the array, if passed, new Array(3) would for example create and array with 3 elements, but all elements are undefined of cause.

Because you use apply , the 2nd parameter of apply is the arguments array you pass in to the method you apply it to.

That means, if your arguments array you apply contains only one element, the default constructor new Array(<numofelemnts>) will get excecuted.

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

It should have been Array.apply(null, [1, 2]) actually. Array.prototype.constructor === Array , and when you do new Array(1, 2) you're not applying it on the Array constructor function but on nothing.

when i put something like Array.prototype.constructor.apply(Array, [3]) it creates an array with 3 empty elements!! Any idea why?

That's how the Array constructor is supposed to work. When it gets called with a single numerical argument, it will create a new empty array with that .length (and you're doing that: new Array(3) ).

My objective is the create a new array from another array.

Use the slice Array method for that:

[1, 2].slice();
// or, complicated, but works with array-like objects:
Array.prototype.slice.call([1, 2]);

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.

You just need to use concat or slice on the original array. You don't need to bother with prototypical calls, because that is reserved for creating a copy of the arguments list, in order to convert it to an array:

var new_array_copy = existing_array.slice(0)

The arguments functionality I am talking about:

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;
}

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 (ie var array = [3]; )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM