1

I am learning about call and apply in javaScript from a online TUT. This function allows more arguments to be passed, rather than having a fixed amount.

var calculate = function(){
        var fn = Array.prototype.pop.apply(arguments);
        return fn.apply(null, arguments);
    };

What I am having difficulty wrapping my head around is this statement.

var fn = Array.prototype.pop.apply(arguments);

The presenter of the of the TUT, explained it as the following:

We are binding the apply method onto the arguments object. This is going to give us the Function Object and assign it to the fn variable. It will also remove the Function Object from the argumentsObject. Because the Array's pop method takes the final element in the array, it removes it from the Array and then assigns to what ever called the method. In this case the fn variable.

What confused me was the following:

We are binding the apply method onto the arguments object. This is going to give us the Function Object

It will also remove the Function Object from the arguments Object.

And when we write in the return statement:

 return fn.apply(null, arguments);

Why are we including null?

Antonio Pavicevac-Ortiz
  • 4,898
  • 8
  • 40
  • 94
  • this code doesnt validate any way i call it – Jacek Pietal Jun 08 '15 at 15:16
  • 2
    in `apply`, the first arguments is the context (the `this`). In `Array.prototype.pop.apply(arguments)`, you're using `arguments`, which is an array-like object (NOT an actual `Array` object), as the context. That's because you can't do `arguments.pop()`, because `arguments` doesn't share `Array.prototype`... it's not actually an `Array` object. – Josh Beam Jun 08 '15 at 15:17
  • 1
    So in the first `apply`, you don't need the second argument. However, in `fn.apply(null, arguments)`, you're passing in `null` as the first argument, because there's no need for a context. But, you pass in `arguments` as the second parameter because it can be used by the function. – Josh Beam Jun 08 '15 at 15:18
  • I don't know why people keep closing this question... – Josh Beam Jun 08 '15 at 15:28
  • arguments is pseudo-array, calling pop on it (get last element = function), then running it on rest of arguments. calculate(1,2,3,4,5,function() { console.log(arguments); }); – Jacek Pietal Jun 08 '15 at 15:32

3 Answers3

2

Array.prototype.pop.apply(arguments);

When you have a function, there's automatically an arguments objects, which is an Array-like object of arguments. If you call this fake function:

someFunction('hello', 'world');

and someFunction looks like this:

function someFunction() {
    console.log(arguments);
}

The console.log will output ['hello', 'world']. However, don't be confused... That is not an Array object! It is an "array-like" object. Therefore, you can't say arguments.pop()... because arguments doesn't have that method (it belongs to Array.prototype). However, normal Array objects do have access to Array.prototype (e.g. [1,2,3].pop() // => [1,2]).

When you say .apply(), the first argument is the context... It sets the this. So really, Array.prototype.pop.apply(arguments) is a clever way of mimicking arguments.pop(). But you can't do arguments.pop(), because it doesn't have a pop method.

In return fn.apply(null, arguments);, null is the first arguments because we don't need to set a new context for this example. arguments is the second arguments because it's being passed in to use with fn.

.apply() returns a function object, so it returns something like this:

function() { ... }

We can then later invoke that function.

By the way, .pop() mutates the original object (in this case, the array-like object arguments). So you're passing in arguments to fn, but it's missing the last item that was in it previously.

Josh Beam
  • 17,535
  • 2
  • 32
  • 63
1

The last argument passed to calculate is assumed to be a function. It is popped from the arguments list. (Using apply because arguments is not a real array.)

This popped function (fn) is called with the rest of the arguments list. (All other arguments passed to calculate). The arguments list no longer contains fn because pop() modifies the original object.

NULL is used because fn is called without a value for this. (See MDN)


If you call calculate for instance like

calculate(2, 3, function(a, b){ return a + b });

it will return 5.

idmean
  • 13,418
  • 7
  • 47
  • 78
1

According to MDN:

Syntax

fun.apply(thisArg, [argsArray])

Parameters

thisArg: The value of this provided for the call to fun. Note that this may not be the actual value seen by the method: if the method is a function in non-strict mode code, null and undefined will be replaced with the global object, and primitive values will be boxed.

argsArray: An array-like object, specifying the arguments with which fun should be called, or null or undefined if no arguments should be provided to the function. Starting with ECMAScript 5 these arguments can be a generic array-like object instead of an array. See below for browser compatibility information.

Community
  • 1
  • 1
tzipp
  • 341
  • 3
  • 7