Antonio Pavicevac-Ortiz
Antonio Pavicevac-Ortiz

Reputation: 7759

Why would you pass 'null' to 'apply' or 'call'?

According to this JavaScript reference:

The value null is a JavaScript literal representing null or an "empty" value, i.e. no object value is present. It is one of JavaScript's primitive values.

function getMax(arr){
  return Math.max.apply(null, arr);  
}

Wouldn't explicitly passing the keyword this be clearer, or at least more readable? Then again, at this point I may not understand why you would use null.

Upvotes: 17

Views: 16634

Answers (5)

Shavais
Shavais

Reputation: 2596

Apply is useful when you want to pass along the responsibility for doing something to a function that is determined at run time, and pass a variable number of arguments to that function. You may or may not have any appropriate "this" context when you're doing that.

For example I use a library I wrote to facilitate listening for and raising application events that uses apply.

I wanted to be able to be able to raise an event like this:

EventManager.raise('some:event-name', arg1, arg2, arg3, ..);

..and have all of the registered handlers for that event get called with that list of arguments (arg1, arg2, etc). So in the raise function, it goes through the handlers that are registered for that event name and calls them, passing all the passed in arguments except for the event name, like this:

var args = [];
Array.prototype.push.apply(args, arguments);
args.shift();
for (var l in listeners) {
    var listener = listeners[l];
    listener.callback.apply(listener.context, args);
}

When a registered handler (listener.callback) is called, apply is used to pass along a variable number of arguments. Here I have allowed the listener to supply a this context for its event handler when the listener is defined, but that context might not be defined or it might be null, and that's perfectly fine.

For a long time the raise function didn't even facilitate using any callback context. I eventually came across a need for it, so I put in support for it, but most of the time I don't really need or use it.

Upvotes: 1

pushkin
pushkin

Reputation: 10227

One case where I have found this useful is when the function I'm calling is already bound to a particular context.

Because bound functions cannot be rebound, and they will always be called with the thisArg that was passed into bind, there is no use in passing a thisArg into call or apply. From source:

The bind() function creates a new bound function (BF).... When bound function is called, it calls internal method [[Call]] on [[BoundTargetFunction]], with following arguments Call(boundThis, args).

Here's an example:

class C {
  constructor() {
    this.a = 1;
  }
}

function f(n, m) {
  console.log(this.a + n + m);
}

let c = new C();
var boundF = f.bind(c, 2); // the context `c` is now bound to f
boundF.apply(null, [3]); // no reason to supply any context, since we know it's going to be `c`

Upvotes: 3

jfriend00
jfriend00

Reputation: 707876

Why would you pass 'null' to 'apply' or 'call'?

When there is no value you wish to specify for the this pointer inside the function and the function you're calling is not expecting a particular this value in order to function properly.

Wouldn't explicitly passing the keyword this be clearer? Or at least more human readable. Then again at this point I may not understand why you would use null.

In your specific case, probably the best thing to pass is the Math object:

function getMax(arr){
  return Math.max.apply(Math, arr);  
}

While it turns out that it doesn't matter what you pass as the first argument for Math.max.apply(...) (only because of the implementation specifics of Math.max()), passing Math sets the this pointer to the exact same thing that it would be set to when calling it normally like Math.max(1,2,3) so that is the safest option since you are best simulating a normal call to Math.max().

Why would you pass 'null' to 'apply' or 'call'?

Here are some more details... When using .call() or .apply(), null can be passed when you have no specific value that you want to set the this pointer to and you know that the function you are calling is not expecting this to have any specific value (e.g. it does not use this in its implementation).

Note: Using null with .apply() or .call() is only usually done with functions that are methods for namespace reasons only, not for object-oriented reasons. In other words, the function max() is a method on the Math object only because of namespacing reasons, not because the Math object has instance data that the method .max() needs to access.


If you were doing it this way:

   function foo() {
       this.multiplier = 1;
   }

   foo.prototype.setMultiplier = function(val) {
       this.multiplier = val;
   }

   foo.prototype.weightNumbers = function() {
       var sum = 0;
       for (var i = 0; i < arguments.length; i++) {
           sum += (arguments[i] * this.multiplier);
       }
       return sum / arguments.length;
   }

   var x = new foo();
   x.setMultiplier(3);
   var numbers = [1, 2, 3]
   console.log(x.weightNumbers.apply(x, numbers));

When the method you are calling .apply() on needs to access instance data, then you MUST pass the appropriate object as the first argument so that the method has the right this pointer to do its job as expected.

Upvotes: 14

Christos
Christos

Reputation: 53958

Calling apply with null as the first argument is like calling the function without providing any object for the this.

What does the apply method do?

The apply() method calls a function with a given this value and arguments provided as an array (or an array-like object).

fun.apply(thisArg, [argsArray])

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.

Further documentation can be found here.

Upvotes: 13

SyntaX
SyntaX

Reputation: 2120

I am bit late to answer this. I will try to give a long descriptive explanation here.

What is null in JavaScript?

The value null is a literal (not a property of the global object like undefined can be). It is one of JavaScript's primitive values.

In APIs, null is often retrieved in place where an object can be expected but no object is relevant.

fun.apply(thisArg, [argsArray])

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.

If you are using 'strict mode', then it is advisable to pass the this or Math as the parameter.

Upvotes: 1

Related Questions