What is Array.apply actually doing

array map
javascript array
array apply python
array slice
javascript apply
call and apply
javascript array apply function to each element
jquery apply function

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

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]

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

resulting in;

[[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]];

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?

Thanks! -Neil

Good question!

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]

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]

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

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]

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.

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.

Function.prototype.apply(), Actually, this has nothing to do with Array. It just happens that you meet when you use Array. I think we should start with Function. call and Function. apply. By Andrie de Vries, Joris Meys . If you have data in the form of an array or matrix and you want to summarize this data, R’s apply() function is really useful. The apply() function traverses an array or matrix by column or row and applies a summarizing function.

It is very intresting example. And pretty good answer by Dan Tao. But I think that I can give a little additional explanation.

In the first case

new Array(5)

creates an empty object, then it passes throw function and gived length of 5. Because of missing any other arguments this object will get no allocated entries.

// Array(5) [ <5 empty slots> ]

And when you trying to "map" those entries nothing actualy happened because of missing real entries.

However, if you try after this step "array[0]" for example, it returns "undefined"...

In the next case you are using "Call" method of Array() function after first "new Array(5)" (but actualy it has no differense "Call" or "Construct" method of call is used with Array function).

Array.apply(null, new Array(5))

So "new Array(5)" already gived as result Array(5) [ <5 empty slots> ] and "Function.prototype.apply()" decomposes this array to the five parameters that Array() function gets in. And in the current step we get:

// Array(5) [ undefined, undefined, undefined, undefined, undefined ]

These are five real entries. And we can do "map()" with them. But there is a litle mistake in your result, because we currently get after

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

a little bit different result

0: Array(5) [ <5 empty slots> ]    
1: Array(5) [ <5 empty slots> ]  ​  
2: Array(5) [ <5 empty slots> ] ​    
3: Array(5) [ <5 empty slots> ] ​    
4: Array(5) [ <5 empty slots> ]

and to get more precise, to get "five on five, undefined" result we need to little upgrade your code

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

this will return "five on five, undefined" array.

0: Array(5) [ undefined, undefined, undefined, … ] 
1: Array(5) [ undefined, undefined, undefined, … ] 
2: Array(5) [ undefined, undefined, undefined, … ] 
3: Array(5) [ undefined, undefined, undefined, … ] 
4: Array(5) [ undefined, undefined, undefined, … ]

But what I'm talking about is that not only "Function.prototype.apply()" has current behavior to decompose array without real entries. I'll give you an example:

Array(...new Array(5)).map(() => Array(...new Array(5)));

this will actualy gived to us exactly the same result - five on five undefined.

If we took a closer look:

  1. In the first action new Array(5) Array() function returns an empty array but with length property value of '5' because it runs in "Construct" mode, and has one parameter (5).
  2. The second and third action Array.apply() | Array(...) first of all spreads Array without elements to 5 parameters and then pass them to an Array().

It's because of "apply()" or "..." behavior of decomposing arrays. When it gets length of an array it auto transform "empty slots" into undefined values.

Referense from Ecma-262/6.0

(http://www.ecma-international.org/ecma-262/6.0/#sec-function.prototype.apply) Function.prototype.apply
    1. If IsCallable(func) is false, throw a TypeError exception.
    2. If argArray is null or undefined, then Return Call(func, thisArg).
    3. Let argList be CreateListFromArrayLike(argArray).

    7.3.17 CreateListFromArrayLike (obj [, elementTypes] )     
        1. ReturnIfAbrupt(obj).
        2. If elementTypes was not passed, let elementTypes be (Undefined, Null, Boolean, String, Symbol, Number, Object).
        3. If Type(obj) is not Object, throw a TypeError exception.
        4. Let len be ToLength(Get(obj, "length")).
        5. ReturnIfAbrupt(len).
        6. Let list be an empty List.
        7. Let index be 0.
        8. Repeat while index < len
            a. Let indexName be ToString(index).
            b. Let next be Get(obj, indexName).
            c. ReturnIfAbrupt(next).
            d. If Type(next) is not an element of elementTypes, throw a TypeError exception.
            e. Append next as the last element of list.
            f. Set index to index + 1.
        9. Return list.
  1. Here in '8a' clause we get "0", "1"... indexNames to pass them in '8b' as argument names of arraylike object (in our case just array, without any 'like') - array["0"], array["1"]...
  2. Each of requested element values returns with "undefined" and then in 8'e' they consecutively appends to the arguments list.
  3. "CreateListFromArrayLike" returns with five arguments of undefined in list representation in '9'clause which is passed to Function.prototype.apply() and will be applied to an Array() (it will be looking like

new Array(undefined,undefined,undefined,undefined,undefined)).

Spread operator uses iteration protokol instead, but in practice they act simulary on this case.

Apply and arrays: three tricks, The apply() method is very handy if you want to use an array instead of an argument Since JavaScript arrays do not have a max() method, you can apply the� 6 What is Array.apply actually doing Jun 29 '19 0 Difference between Array.apply(null, Array(x) ) and Array(x) Jun 29 '19 0 What's the point of callback implementation inside function declaration?

The Array constructor , when passed with a single numeric value (Let's say n) , creates a sparse Array of length n and has zero elements in it... so .map() wont work on it as explained by Dan Tao...

let ar = Array(5); // Array(5) [ <5 empty slots> ]

So , you can use .fill() method , that changes all elements in an array to given value, from a start index (default 0) to an end index (default array.length). It returns the modified array... So we can fill the empty (sparse) array with "undefined" value... It won't be sparse anymore...And finally, you can use .map() on returned array...

let ar = Array(5).fill(undefined) ; // [undefined,undefined,undefined,undefined,undefined]
let resultArray = ar.map(  el => Array(5).fill(undefined) );

this resultArray will be a 5*5 array with every value of 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, undefined ] ]


About apply, how to understand Array. apply (null, {length: 5 , Such a literal enumerates the array elements; an element's position implicitly the number of elements, so you'd have to write your own function for doing so. apply() translates holes to undefined s in empty arrays, but it can't be used to plug � So in just a few words: there is no problem with array_map() and array_walk().You are talking about some strange errors appearing, 99% because you did something wrong. You could not fix it, and you are advising other people to use foreach because of that, instead of fixing their code or spending a little time to understand optimized array functions.

JavaScript Function Apply(), The map method transforms an array by applying a function to all of its In terms of what the computer is actually doing, these two approaches are also quite� Really we just want the push function, and b.push.apply(a, b) accomplishes exactly the same thing -- the first argument of apply supplies the this for the applied function. I thought it might make more sense to directly use the methods of the Array object: Array.push.apply(a, b) .

Chapter 18. Arrays, forEach(function(item, index, array) { // do something with item }); Actually, a comparison function is only required to return a positive� It might be desired to do some tasks related to the context object but without actually using it inside the lambda argument. An example can be logging. As described in the official Kotlin coding conventions, using also is the recommended way to solve scenarios like the one shown next: val num = 1234.also { log.debug("the function did its job!")

Higher-Order Functions :: Eloquent JavaScript, To understand Call(), apply(), bind() methods of javascript, the first thing we should that using .call() or .apply() actually invokes my function, so instead of doing this: But arguments is an array like object, not a real array. I am reluctant to add this datatype as SQLite doesn't actually support array type. With array type you also get features like array of numbers, strings and thus engine level validations. For Postgres we even support Array(ENUM) which I dont think will work properly in SQLite.

  • Worth mentioning for anyone who wants to bypass the confusing Array.apply(null... thing, that you can do Array(5).fill(Array(5)) to get an array of five sparse 5-length arrays; or Array(someLength).fill(someDefault).map(someFunction) to map someFunction over an array of someLength. For example Array(1000).fill(1).map((n,i) => n+i) gives you an array of numbers from 1 to 1000
  • So, in one case, the indexes weren't defined, and in the other, the indexes were defined as undefined?
  • @KevinB: It almost makes me sad to say it, but... yep. This is the same reason why arr[1] = undefined; is not functionality equivalent to delete arr[1];
  • @DanTao Thanks for the explanation. If I'm understanding you correctly, you're saying that when I use Array.apply, I'm actually using the Function.prototype instead of the Array.prototype?
  • @Neil Yes. Array.apply is used because both map and apply are defined for Array but only apply is defined for Function.
  • I propose this to be selected as the answer