5

In javascript there is a callback, and functions are first-class objects right? so i can pass a function as an argument however if i pass console.log() it doesn't work why is that isn't it a function as well?

setTimeout(function(){console.log("hello")},5000);

this code is valid however

setTimeout(console.log("hello"),5000);

produces an error, why is that?

  • 1
    Because you are queuing up the *result* of `console.log(...)` (it returns `undefined`), not the actual call to `console.log(...)`. –  Jun 05 '18 at 21:07
  • 1
    you should be able to pass it around willy-nilly since they recently bound `this` to `console` for its methods... – dandavis Jun 05 '18 at 21:10

5 Answers5

3

When you call console.log with some argument, the argument is printed to console and the function returns undefined.

So when you do:

setTimeout(console.log("hello"),5000);

"hello" will be printed, but what you're essentially doing is:

setTimeout(undefined, 5000);

In the other example (that works) you create a new function, but you do not call it. So you pass this new function to setTimeout, and that is why it works.

Phillip
  • 6,033
  • 3
  • 24
  • 34
3

The reason that the following code

setTimeout(console.log("hello"),5000); 

fails is because console.log() is invoked directly inside the setTimeout parameter and it always returns undefined (more info: MDN Documentation on Console.log). This means you are essentially running setTimeout(undefined,5000);

You need to provide a function declaration that is not invoked. If you wrap the code inside of a function declaration and do not invoke it, setTimeout will invoke it for you after the specified time lapses. This is why your first statement works, you provide a function declaration:

setTimeout(function(){console.log("hello")},5000);

If you had invoked the function you provided in the first parameter it would also return undefined and "hello" would be output immediately.

So if you provide a function declaration it will work:

setTimeout(()=>{console.log("hello")},5000);

Another way to use console.log directly without a function declaration is to bind it to a variable (more info: MDN Documentation on Function.prototype.bind). An example using .bind prototype:

setTimeout(console.log.bind(null,"hello"),5000);

The code above binds "hello" to invocation of console.log. The first parameter is null in this example but it is the this context.

setTimeout also allows you to pass variables that you want the function to be invoked with. See MDN Documentation on setTimeout

For example to pass a variable:

setTimeout(console.log,5000,'hello');

In the above example you are telling setTimeout to invoke console.log in 5 seconds with the variable (in this case a sting) of 'hello'.

Evans
  • 631
  • 5
  • 12
1

Invoking console.log('hello') will return undefined so you are not really passing it to setTimeout, It will print "hello" though but not inside a callback.
In most cases it wont throw an error (as you can see in the example below).

What you can do however is pass console.log (the function) and a 3rd argument the string "hello" in our case.

Running example with all 3 cases:

setTimeout(console.log("hello"),500);
setTimeout(function(){console.log("hello2")},500);
setTimeout(console.log,500,"hello3");
Sagiv b.g
  • 30,379
  • 9
  • 68
  • 99
0

It produces an error since it evaluates console.log(...), which evaluates to undefined, and thus is not a function.

bc1105
  • 1,270
  • 8
  • 8
0

setTimeout accepts the function as a parameter, not the function call. console.log() is basically invoking the function/method but setTimeout requires the reference or more specifically called the callback.

In your example:-

setTimeout(function(){console.log("hello")},5000);

you can call it like

var callback = function(){console.log("hello")};
setTimeout(callback,5000);

The callback will be called by setTimeout later in future. I hope it clears everything.

pvnarula
  • 2,771
  • 18
  • 22