6

I'm going through John Resig's JavaScript ninja tutorial and on #51 I see this:

// Find the largest number in that array of arguments 
var largestAllButFirst = Math.max.apply( Math, allButFirst ); 

allButFirst is just a small array of integers. I believe I understand what apply does, but I can't understand why Math is being passed as an argument to apply.

Jake Sellers
  • 2,350
  • 2
  • 21
  • 40

3 Answers3

3

The first parameter of the .apply is the context. Inside the function body the this keyword will reference that value.

Example:

function sum(a){ return this + a; }
sum.apply(1, [1]); // will return 2
// or with .call
sum.call(1, 1); // also returns 2

By default if you call Math.max the context (the this keyword) is automatically set to Math. To keep this behavior Math is passed as the first parameter in apply.

lionel
  • 875
  • 8
  • 15
1

Passing it Math is not necessary, anything will work here. Math indicates the context of the operation, however max does not require a context. This means that Math.max.apply(undefined, allButFirst) will also work. See this answer.

Community
  • 1
  • 1
PlasmaPower
  • 1,864
  • 15
  • 18
  • 4
    @JakeSellers For `Math.max` specifically, and I'm sure a few other functions, it really doesn't matter. The point is that `Math.max` **doesn't rely on or use the `this` value**...but many other function **do**. While it's technically optional, I would suggest always passing it, because you **normally** call it like `Math.max()` (the `this` value is `Math`). I'd rather be safe than sorry for such a little thing, as well as consistent. – Ian Mar 12 '14 at 21:59
  • @ian in [the docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/arguments) for arguments, you can see they use `Array.prototype.slice.call(arugments)` to change the args into an array with no context given to call. What is your opinion on this? I use this technique sometimes, should I not worry about it or pass a context, perhaps just `this` for the local function context? – Jake Sellers Mar 12 '14 at 22:19
  • 1
    @JakeSellers That is a little different. `slice` requires the `this` value to be set to an array (or array-like object, like `arguments`). Since `arguments` isn't an array, it doesn't have a `slice` method. But since it's array-like (has a `length` property), you can call `Array.prototype.slice` and provide an array-like object as `this` (that's what the `.call()` is for). Like I said for `Math.max` - it **doesn't** use `this` – Ian Mar 12 '14 at 22:23
  • 1
    @JakeSellers: In that case `arguments` becomes `this` inside the function. It's like calling `arguments.slice()` **iff** arguments was an array. The first argument passed to `.call` or `.apply` is always the value `this` will refer to inside the function. – Felix Kling Mar 12 '14 at 22:24
  • @FelixKling ok I think all the pieces fit together now, thanks. – Jake Sellers Mar 12 '14 at 22:30
0

From Mozilla docs:

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.

So, in your example, Math is being used as the context for the function (if the keyword this is used inside).

If no thisArg is used, then the default is the global object. So, it is good practice to give some context if possible.

Davin Tryon
  • 66,517
  • 15
  • 143
  • 132