Why console.log doesn't work as an argument? [duplicate] - javascript

This question already has answers here:
What is the difference between a function call and function reference?
(6 answers)
Closed 12 months ago.
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?

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.

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'.

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");

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

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.

Related

Uncaught (in promise) TypeError: stringConcat() is not a function : Async String Concatenation doesnt work [duplicate]

I have the following function
function hello() {
alert("hi!");
}
Take this piece of code:
var elem = document.getElementById("btn");
elem.onclick = hello;
My question might be a bit hard to understand, so bear with me:
What EXACTLY differentiates THIS piece of code from a normal call, or what makes this piece of code require a reference to the function variable rather than a regular call? (hello();)
How can I know where I'm supposed to give a reference to the function, and when I'm supposed to actually call it?
Well, the onclick property expects a reference to a function, for it to execute when the element is clicked. Normally it's either:
element.onclick = funcRef;
or
element.onclick = function () {
funcRef();
};
(but of course, it's best to use addEventListener and attachEvent)
Notice how both of them are references to functions, not calling.
When something expects a reference, you don't call it...you assign a reference to it (first example).
When you want to specifically call a function, you call it with () (second example). But notice how in the second example, there's still a reference to a function that's assigned to onclick - it's just an anonymous function.
Probably the more important part:
Some people think you want to do this:
element.onclick = funcRef();
But that immediately executes the function (because of the ()), and assigns its return value to onclick. Unless the return value is a function, this isn't what you want.
I think the moral of the story is that when you want/need something to execute right now, you call the function. If the function is wanted for later use or needs stored, you don't call it.
Do you want it to execute NOW? Then call it.
a=hello() means "Call hello() ASAP, and set its return value to a".
On the other hand, a=hello means "a is an alias for hello. If you call a(), you get the same results as calling hello()"
You use the latter for callbacks, etc, where you want to tell the browser what you want to happen after an event occurs. For example, you may want to say "call hello() when the user clicks" (as in the example). Or, "When the AJAX query returns a result, call the callback() function on the returned data".
How can I know where I'm supposed to give a reference to the function, and when I'm supposed to actually call it?
Do you need the function to run now?
Than add the () to execute it
Do you need to function to be referenced so it is called later?
Do not add the ().
Pretty much all statements in JavaScript have a return value. Unless otherwise specified, functions in JavaScript will return undefined when called. So, the only context in which it would make sense to call your function in this assignment statement if it were to return a function:
function hello() {
return function() {
alert("hi!");
}
}
elem.onclick = hello();
A reference to your function is needed somewhere no matter how it gets called. The difference here is that you are not explicitly calling the hello function. You are assigning a reference to that function to the elem DOM node's onclick event handler so that when onclick is fired for that Node, your function gets called.
hello() means you call that function, which means the function will be executed directly.
while when you have elem.onclick = hello, this is called a callback. Where hello doesn't get executed directly but only when a certain event is fired (in this case when there's a click on the element)

How does the invocation of this function work?

function functionOne(x){console.log(x);};
function functionTwo(var1) {
};
functionTwo(functionOne(2));
why does functionTwo work there ? it doesn't suppose work, does it?
because there is not an operation.
functionTwo(functionOne(2));
This means "immediately call functionOne, passing in 2. Then pass the result into functionTwo". So functionOne does its thing, logging out 2, and then returns undefined. And then undefined is passed into functionTwo.
Instead, if you're trying to experiment with callbacks you need to pass a function in, as in:
functionTwo(() => functionOne(2));
Once you do that, you'll no longer see a console.log unless you add some code to functionTwo.

Calling vs invoking a function

Up to this point, I thought "calling" and "invoking" a function meant the same thing. However, in a YouTube tutorial it said to invoke a function by calling it. My first thought was that the wording was a mistake, but on W3Schools' page on Function Invocation, it says:
It is common to use the term "call a function" instead of "invoke a
function" ... In this tutorial, we will use invoke, because a
JavaScript function can be invoked without being called.
Okay, so there's a difference. What is it?
Your reference text:
It is common to use the term "call a function" instead of "invoke a
function" ... In this tutorial, we will use invoke, because a
JavaScript function can be invoked without being called.
Now let me rephrase it:
It is common to use the term "call a function" instead of "invoke a
function" ... In this tutorial, we will use the term invoke instead of call, because a
JavaScript function can be invoked indirectly like fn.call() and fn.apply() without being called directly like fn().
So, when I do fn(), it's invoked directly and when I do it like fn.call(), it's invoked indirectly but in both cases, the function is being invoked. Otherwise, I see no difference here and I can also say that I can call a function in many ways, for example:
fn(); // I'm calling it
fn.call(); // I'm calling it
fn.apply(); // I'm calling it
So, the difference is semantic but both are interchangeable, IMO. BTW, I wrote a comment above, under the question and I would like to put it here, which is:
IMO, that's a misleading statement. Maybe there are some indication of
call/apply or something else but it's totally confusing.
The difference is semantic and subtle. When you call a function, you are directly telling it to run. When you invoke a function, you are letting something run it.
There is one way to call a function:
myFunction()
Here, you are invoking the function (letting it run) by calling it directly.
There are many ways to invoke a function (given throughout different comments and answers). Here's one example:
function invoker(functionName) {
functionName()
}
invoker(myFunction)
Here, by calling invoker, you are invoking myFunction, which is being called indirectly.
Yes, in most cases we use both to refer the execution of a function.
There are 2 ways to reach place B from your HOME.
Direct/Automatic way (Invoke), i.e. if you choose first way, you do not need to walk. Someone will automatically take you to place B.
Indirect way (Call), i.e. if choose second way, you only need to reach A(by walk). Someone is there at place A to automatically take you to place B.
Have a look at the below image. I think it will clear your doubt.
In case of Calling, you originally refer to the statement that actually calls the function.
In case of Invoking, you indirectly refer to calling statement to actually invoke/run the function.
Many people use the term calling and invoking interchangeably but that's not right. There is a very slight difference between calling and invoking a function. In JavaScript functions can be invoked without being called which means that the code inside the body of the function can be executed without creating an object for the same. It is tied to the global object. When there is no individual object, the value of this is associated with the global object.
There is also a difference between call and apply, the fundamental difference is that call() accepts an argument list, while apply() accepts a single array of arguments. A different this object can be assigned when calling an existing function. this refers to the current object, the calling object. With call, you can write a method once and then inherit it in another object, without having to rewrite the method for the new object.
So, the major difference between invoking and calling comes in terms of the this object. Calling let's you set the this value whereas invoking just ties it to the global object.
"function invoked" means a function got executed
"function called" means that a function was called by another function and then executed
"function invoked without being called" is a function that got self invoked without being called by another function
example of a self invoking function calling another function:
var f = (function() {
foo();
})(); ///() here means it self invoked -- without being called directly.
var foo = (function() {
///Do something here
});

String.call.call type? [duplicate]

This question already has answers here:
"object is not a function" when saving function.call to a variable
(3 answers)
a is a function, then what `a.call.call` really do?
(2 answers)
Closed 5 years ago.
This is true (run it in the console in Google Chrome):
typeof String.call.call === 'function'
But calling it as
String.call.call() throws an error saying it's not a function:
Uncaught TypeError: String.call.call is not a function
at :1:13
Why trying to call a function (as per its typeof definition) throws an error saying it's not a function? Is it actually a function or not?
Note this happens to other classes such as Number, Function or others that inherit the .call method.
Let's try to break this down into more manageable pieces.
String is a constructor (or a static function / constructor hybrid, whatever you want to call it), and as such, it inherits from Function.prototype, because it is a function.
call is a function that executes its context (the this) with the context given to it in the first parameter:
console.log(String.call(true));
console.log(Array.call(null));
console.log(Function.call('so?'));
console.log(Object.call(/notice me/));
Let's look at a more official definition for Function.call():
The call() method calls a function with a given this value and arguments provided individually.
function.call(thisArg, arg1, arg2, ...)
Now, the interesting part here is noting that these three are identical:
'use strict';
var callRef = String.call; // Function.call, Array.call, Boolean.call, all of them are ===
console.log(String(/make me into a string/));
console.log(String.call(undefined, /make me into a string/));
console.log(callRef.call(String, undefined, /make me into a string/));
The callRef.call(String) means, call callRef() with the context of String, which is to say, execute String() with the context and parameters provided in the following arguments.
As we recall, the context doesn't really matter, but now we know that the first parameter of callRef.call() does matter, because it determines what function to execute, because it's telling callRef() what its context is, which gets executed as a function with the context provided in the next parameter.
Now reflecting on the initial question, what happens when we attempt to execute String.call.call()? Well, if a parameter is not specified, it is undefined, and we know that typeof undefined !== 'function'.
So here's my final answer:
String.call.call() is indeed a function... but all it's doing is attempting to execute undefined as a function, which obviously isn't.
String.call.call();
I hope this has been an interesting and informative explanation.

Why does setTimeout require code to be enclosed in function?

In JavaScript, the setTimeout function requires code to be enclosed in a function.
Examples of invalid timeouts:
window.setTimeout(console.log('PING'),3000)
function ping(){console.log('PING')};window.setTimeout(ping(),3000)
Example of valid timeouts:
window.setTimeout(function(){console.log('PING')},3000)
function ping(){console.log('PING')};window.setTimeout(function(){ping()},3000)
Now my question: why? I understand why normal code might need to be enclosed in a function, but why is it ALWAYS necessary to enclose code in function(){}?
It doesn't always require an anonymous function. You can also pass a function reference as the first argument, for example, let's assume you have a function called log defined. You can validly write:
function log()
{
console.log( 'PING' );
}
window.setTimeout( log, 200 );
Notice that we don't pass the parentheses with the first argument here.
However, you're not able to pass parameters directly to log() in this instance, so it's necessary to wrap the function call inside an anonymous function.
The code is required to be enclosed in a function because, the setTimeout function does not execute individual lines of code. It takes two, arguments - the first argument is a callback function, and the second argument is the time in milliseconds. The callback function will be called by the setTimeout function internally after the specified amount of time passes.
In the example you gave
window.setTimeout(function(){console.log('PING')},3000)
you pass an anonymous function which would be called after 3000 milliseconds or 3 seconds.
Basically because setTimeout is an asynchronous operation and you need to give what to do next once the timeout is done (i.e. you give a callback function).
Unless JavaScript runtime could block the UI thread and resume execution once the setTimeout ends, you need to provide some executable code to perform an action once the asynchronous operation has been completed:
setTimeout(function() {
// Do stuff after 1 second
}, 1000);
In the other hand, what would be the point of giving a function return value as argument? Check this wrong code to be more illustrative:
// You do some action even BEFORE the timeout operation has been completed?
setTimeout(doStuff(), 1000);
Further reading
Callbacks in Wikipedia
It doesn't need to be enclosed in function(){} but it does need to be a parameter of type Function.
In the case of window.setTimeout(console.log('PING'),3000), what would happen is that console.log() would immediately be executed and the return value (which is undefined) would be passed to the setTimeout function. This code isn't passing a function as a parameter, it's passing the return value of a function as a parameter. Essentially, it's just a shorter way of writing this:
var retVal = console.log('PING'); // retVal === undefined
window.setTimeout(retVal,3000);
That's not special to setTimeout. console.log without () is a function, but console.log() means to invoke that function.
There are other methods to pass a function in to setTimeout, but the anonymous function is typically the cleanest.
Technically, this would work, too:
window.setTimeout(console.log,3000)
but it would not allow you to specify a parameter, making it rather useless here. This could be avoided by binding parameters:
window.setTimeout(console.log.bind(null,'PING'),3000)
In this case, bind is a function which is being invoked (as you can see by the fact it has parameters supplied), so just as before bind is immediately executed. However, bind is a function whose return value is itself a function, and it's that returned function that is passed to setTimeout and called three seconds later. This technique (which you will see used with bind, call, and apply) is called partial application which really just means that you transform a function taking some parameters into a function taking fewer parameters (in this case, zero parameters) by specifying the parameters now but executing the function later.
Because setTimeout is a function that takes two argument - a function, and a number of seconds before that function executes.
https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout
Parameters:
func: A function to be executed after the timer expires.
code: An
optional syntax allows you to include a string instead of a function,
which is compiled and executed when the timer expires. This syntax is
not recommended for the same reasons that make using eval() a security
risk.
delay: Optional The time, in milliseconds (thousandths of a
second), the timer should wait before the specified function or code
is executed. If this parameter is omitted, a value of 0 is used. Note
that the actual delay may be longer; see Reasons for delays longer
than specified below.
param1, ..., paramN Optional Additional
parameters which are passed through to the function specified by func
once the timer expires.
Apparently YOU can just use code, as per the second argument above, but I have never seen it done.

Categories

Resources