JavaScript “new Array(n)” and “Array.prototype.map

2018-12-31 15:04发布

I've observed this in Firefox-3.5.7/Firebug-1.5.3 and Firefox-3.6.16/Firebug-1.6.2

When I fire up Firebug:

    >>> x = new Array(3)
    [undefined, undefined, undefined]
    >>> y = [undefined, undefined, undefined]
    [undefined, undefined, undefined]

    >>> x.constructor == y.constructor
    true

    >>> x.map(function(){ return 0; })
    [undefined, undefined, undefined]
    >>> y.map(function(){ return 0; })
    [0, 0, 0]

What's going on here? Is this a bug, or am I misunderstanding how to use new Array(3)?

13条回答
伤终究还是伤i
2楼-- · 2018-12-31 15:19

With ES6, you can do [...Array(10)].map((a, b) => a) , quick and easy!

查看更多
墨雨无痕
3楼-- · 2018-12-31 15:19

Not a bug. That's how the Array constructor is defined to work.

From MDC:

When you specify a single numeric parameter with the Array constructor, you specify the initial length of the array. The following code creates an array of five elements:

var billingMethod = new Array(5);

The behavior of the Array constructor depends on whether the single parameter is a number.

The .map() method only includes in the iteration elements of the array that have explicitly had values assigned. Even an explicit assignment of undefined will cause a value to be considered eligible for inclusion in the iteration. That seems odd, but it's essentially the difference between an explicit undefined property on an object and a missing property:

var x = { }, y = { z: undefined };
if (x.z === y.z) // true

The object x does not have a property called "z", and the object y does. However, in both cases it appears that the "value" of the property is undefined. In an array, the situation is similar: the value of length does implicitly perform a value assignment to all the elements from zero through length - 1. The .map() function therefore won't do anything (won't call the callback) when called on an array newly constructed with the Array constructor and a numeric argument.

查看更多
不流泪的眼
4楼-- · 2018-12-31 15:20

I had a task that I only knew the length of the array and needed to transform the items. I wanted to do something like this:

let arr = new Array(10).map((val,idx) => idx);

To quickly create an array like this:

[0,1,2,3,4,5,6,7,8,9]

But it didn't worked because: see Jonathan Lonowski's answer a few answers upper.

Solution could be to fill up the array items with any value (even with undefined) using Array.prototype.fill()

let arr = new Array(10).fill(undefined).map((val,idx) => idx);

console.log(new Array(10).fill(undefined).map((val, idx) => idx));

Update

Another solution could be:

let arr = Array.apply(null, Array(10)).map((val, idx) => idx);

console.log(Array.apply(null, Array(10)).map((val, idx) => idx));

查看更多
何处买醉
5楼-- · 2018-12-31 15:20

Just ran into this. It sure would be convenient to be able to use Array(n).map.

Array(3) yields roughly {length: 3}

[undefined, undefined, undefined] creates the numbered properties:
{0: undefined, 1: undefined, 2: undefined, length: 3}.

The map() implementation only acts on defined properties.

查看更多
皆成旧梦
6楼-- · 2018-12-31 15:24

If you are doing this in order to easily fill up an array with values, can't use fill for browser support reasons and really don't want to do a for-loop, you can also do x = new Array(3).join(".").split(".").map(... which will give you an array of empty strings.

Quite ugly I have to say, but at least the problem and intention are quite clearly communicated.

查看更多
栀子花@的思念
7楼-- · 2018-12-31 15:28

The arrays are different. The difference is that new Array(3) creates an array with a length of three but no properties, while [undefined, undefined, undefined] creates an array with a length of three and three properties called "0", "1" and "2", each with a value of undefined. You can see the difference using the in operator:

"0" in new Array(3); // false
"0" in [undefined, undefined, undefined]; // true

This stems from the slightly confusing fact that if you try to get the value of a non-existent property of any native object in JavaScript, it returns undefined (rather than throwing an error, as happens when you try to refer to a non-existent variable), which is the same as what you get if the property has previously been explictly set to undefined.

查看更多
登录 后发表回答