Call apply method with arguments in JavaScript
Asked Answered
A

5

19

I wanted to invoke a function using the javascript apply() method. This works fine if the function has no arguments. i.e.

function test()
{
  console.log(this);
}

body = document.getElementsByTagName("body")[0]; // shortcut to body element

test.apply(body); // returns [object HTMLBodyElement]

But I can't seem to do the same thing to invoke a function that has arguments:

function test(msg)
{
  console.log(msg);
}

body = document.getElementsByTagName("body")[0]; // shortcut to body element

test(this).apply(body); // mysteriously returns the correct result, then
// typeError: 'undefined' is not an object (evaluating "test(this).apply".

The examples above are completely trivial but the grain of my question is: How do I use the apply() method to invoke a function with arguments.

Annam answered 6/10, 2011 at 15:37 Comment(0)
V
32

apply takes two arguments:

test.apply(null, [body]);

The first argument sets the value of this when the function is executed. The second is an array of parameters for that function.

In your examples you could rewrite it as follows:

function test() {
    console.log(this);
}

and call it as follows:

test.apply(this);
Valdis answered 6/10, 2011 at 15:40 Comment(5)
Important to note that the second argument should be an array, rather than just a single element. test.apply(null, body) breaks for me (Chrome 35), but test.apply(null, [body]) works.Bipinnate
What is the real use of using apply method is there any benefits?Cyril
I'm sure there are a whole host of real uses. Some that spring to mind are to monkey patch functions (including built-ins), for variadic functions, and for specifying this for callback functions.Valdis
@JohnKeyes lets just say I have a function like function test(msg){..} & I need to set the this value & also want message value in msg only? test.call(newThisObj,'new this obj set'); value would be available in arguments instead of msgAeneous
@Aeneous you can use the following test.apply(this, ['new this obj set']);Valdis
W
8

First notice that you are actually invoking your function immediately, the line:

test(this).apply(body);

Fails because at first, you call the test function passing this as an argument, and then you try to access an apply property on the function's result, which is undefined since your function doesn't return anything.

That property access on the undefined value is giving you the TypeError exception.

Now, let's see what you actually want to do, if you want to pass the value of the body variable as the argument of your function, setting the outer this value, as the this value of test, you can do:

test.apply(this, [body]);

But that's why the call method exists, when you know exactly which arguments to pass, you don't need to create an array for nothing, you just pass the arguments:

test.call(this, body);

The apply method is really useful when you deal with for example a dynamic number of arguments, when you know which arguments want to pass, and still have the ability of setting the this value, call is just what you need.

Wendeline answered 6/10, 2011 at 15:45 Comment(1)
Documentation for call: developer.mozilla.org/en/JavaScript/Reference/Global_Objects/…Valdis
C
6

With apply you send an array of arguments as its second argument:

test.apply(body,["Hello World"]);

Here is the apply documentation on the MDN docs https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/apply

Conception answered 6/10, 2011 at 15:39 Comment(2)
@JohnKeyes is right, I should have paid more attention to my copy and paste. I corrected the syntax error.Conception
I'll delete my comments here if you like. They're not adding to the answer.Valdis
L
0

Be sure to add in the argument:

test.apply(body, ["my message here"]);
Ligature answered 6/10, 2011 at 15:40 Comment(0)
A
0

apply can take two arguments

  1. An object to bind

  2. An array of arguments to be passes to the method

    test.apply(obj, arr);

In this case the obj is body and arr is array of arguments.

Remember to accept the params in the invoked funtion as below

function test(...params)
 {
   console.log(this);
 }
Antinode answered 25/3, 2023 at 19:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.