Why must a call to a function be enclosed in function() - javascript

Coming from a standard programming language, I find this snippet of javascript hard to understand:
(from http://www.w3schools.com/js/js_timing.asp)
var myVar=setInterval(function () {myTimer()}, 1000);
function myTimer() {
var d = new Date();
document.getElementById("demo").innerHTML = d.toLocaleTimeString();
}
Why is the call to myTimer() further enclosed in function(){}, it is a function. And isn't setInterval() expecting a function? So why not just refer to the function directly? as in:
var myVar=setInterval(myTimer(), 1000);
What I also don't understand is that the above actually runs once. Why is that? (If it is incorrect then it should not work at all)
Thanks

To pass the reference just use the function name without ().
var myVar=setInterval(myTimer, 1000);
When () is used the function is invoked and the returned value is passed to the setInterval

So why not just refer to the function directly? as in:
var myVar=setInterval(myTimer(), 1000);
Because then the result of myTimer call is passed. Functions aren't different to any other value when you pass them to other functions.

Related

Why we not use () while calling function in EventListener in JavaScript

I am new to JavaScript. I read a code which is:
document.getElementById("myBtn").addEventListener("click", displayDate);
function displayDate() {
document.getElementById("demo").innerHTML = Date();
}
I read the documentation, in this I get that the second parameter of addEventListener would be a function like the bellow (here after function we use () brackets)
document.getElementById("myBtn").addEventListener("click", function(){
document.getElementById("demo").innerHTML = Date();
});
according to my knowledge, we must use () after a function which is not in the first example. Even if I use than it doesn't work. So my question is why we can't use () if we create a separate function. I hope you understand my question.
The parentheses mean different things in these scenarios. The parentheses that go after the function keyword denote a list of arguments that you provide to the function, e.g. function(a, b, c) signifies that the function takes 3 arguments, a, b, and c. The parentheses that go after displayDate represent the fact that you are calling the function with no parameters, and passing the return value to addEventListener. Since displayDate returns undefined, you are essentially setting undefined as an event listener, which will do nothing.

set Interval in javascript

I am beginner in javascript.
There is strange thing in javascript and I feel stupid
//First statement
var myVar = "Hello";
function hello() {
document.getElementById("demo").innerHTML = myVar;
}
//second statement
var myVar = setInterval(myTimer, 1000);
function myTimer() {
document.getElementById("demo").innerHTML = new Date().toLocaleTimeString();
}
Why the second function work without invoked it ?
Unlike the first ? This caused a lot of problems to me !
Why the second function work without invoked it ? Unlike the first ?
You are passing the function myTimer to setInterval. setInterval calls the function every 1000ms. So while it is not you who directly calls the function, it is still called (by setInterval). setInterval's whole purpose is to call the function that you pass to it as argument.
In contrast, you are not doing anything with hello. You are neither calling it directly, nor are you passing it to any other function that could call it.
From what I can gather from the comments, you seem to be confused as to why the myTimer() function works. Here's a brief explanation:
On this line
var myVar = setInterval(myTimer, 1000);
you are calling the setInterval() function. That function takes 2 parameters, which you have defined. The first one is a function; the code to be executed. The second one is the delay between each execution of said function.
On the next line, you have declared the variable myTimer to be a function which is executed with the setInterval.
Have a look at the MDN documentation for details. Specifically, it says:
var intervalID = window.setInterval(func, delay)
The parameters are defined as:
func: A function to be executed every delay milliseconds.
and
delay: The time, in milliseconds (thousandths of a second), the timer should delay in between executions of the specified function or code.

Passing variables VS passing values

I would love to understand the difference between:
var the_timeout = setTimeout("alert(the_string);", 60000);
and:
var the_timeout = setTimeout("alert(" + the_string + ");",60000);
I understand that the first passes the variable, and the second passes the value - but what does that mean exactly and why does it matter? Why is the value passed in the second example?
Also (I hope this is the same subject), why does this work:
var timeout=setTimeout("someFunction();", 3000)
While this doesn't:
var timeout=setTimeout(someFunction(),3000);
When calling a function, someFunction() works, so why do I have to add quotes when using setTimeout()?
I think you're confusing the distinction between pass-by-value and pass-by-reference with this. In the examples you mentioned, there is no difference.
However,
var timeout=setTimeout("someFunction();", 3000)
Works and:
var timeout=setTimeout(someFunction(),3000);
Doesn't because in the second case, someFunction() would run so that it can then pass the result/return value to setTimeout. That's why you pass it as a string so that setTimeout can eval it on its own. Unless, of course, if someFunction() itself returns a function that setTimeout can use as a callback.
However, as zerkms pointed out in a comment, you should pass callbacks instead:
var timeout = setTimeout(function() { someFunction(); }, 3000);
This also has the effect that setTimeout can then call the callback whenever it wants. A major benefit is that you can pass any regular function so that you can benefit from the editor you may be using, instead of packing it all into a string:
var myTrigger = function() {
someFunction();
};
var timeout = setTimeout(myTrigger, 3000);
This will parse execute the code within the string, 60 seconds later.
var the_string = "Hello";
setTimeout("alert(the_string);", 60000);
the_string = "Goodbye";
This means alert(the_string) is executed, just as if it was regular code. So it would alert "Goodbye". This is because when the code is eventually executed, the updated value of the_string is used since you are passing the variable.
But this does something subtly different.
var the_string = "Hello";
setTimeout("alert(" + the_string + ");",60000);
the_string = "Goodbye";
Now we are creating a new snippet of code on the fly. The snippet we are creating is alert(Hello);. But Hello is a variable with no value because you didn't get the quotes right.
But lets say you meant this:
var the_string = "Hello";
setTimeout("alert('" + the_string + "');",60000);
the_string = "Goodbye";
Now this will work, because the code it generates is alert('Hello');. Which at first glance appears to do the same thing. But because the generated code now includes literally a hardcoded string, so when the_string changes, the change doesn't make it into generated code because it was hardcoded into the snippet.
Based on that, this is simple:
setTimeout("someFunction();", 3000)
The code in the string is executed after the delay. In this case, someFunction() is executed.
But this is totally different:
setTimeout(someFunction(),3000);
In this case, someFunction() is executed immediately, and it's return value is passed as the first argument to the setTimeout() function. So it won't do what you expect at all.
Most of this has to do with the quirks of eval and generated code, as setTimeout(string,delay) is a form of eval. And none of this is a problem if you don't use eval, and you don't pass a string to setTimeout().
Passing a string to setTimeout leads to eval, eval leads to wierd crazy bugs, wierd crazy bugs lead to pain, pain leads to sufferrriing.
Instead you pass a function instead. It's better in every single way.
// pass an anonymous function to run some code later
var the_string = "Hello";
setTimeout(function() {
alert(the_string);
}, 60000);
the_string = "Goodbye";
// alerts "Goodbye" 60 seconds later
// pass an anonymous function to run some code
setTimeout(function() {
someFunction();
}, 3000);
// or pass a reference to a function to execute, note lack of ()
setTimeout(someFunction, 3000);

How to figure out how to use setInterval correct with this jQuery script

This is a continuation of a previous question I asked.
I'm trying to display a clock based on a pre-determined time value .. not the current clients time.
Here's my jQuery:
$(document).ready(function () {
var currentTime = new Date('3/09/2010 9:27:29 PM');
setInterval("DisplayTime(currentTime, $('.answer-body'))", 1000);
})
function DisplayTime(currentTime, destination) { ... }
Now inside the DisplayTime function, i was showing some custom text, calling the destintion.html(..) to display that custom text. And finally, after I display the text, I was thinking of adding 1 second to currentTime so when the next iteration of the interval, it's not using the original time value, but 1 second later.
Problem: I cannot pass in the currentTime variable to the setInterval function. I don't particularly want to have an anonymous function here, unless I have no choice.
How can I refactor my bad code?
So every second, the time is re-displayed with the new second being added.
On the contrary, you should use an anonymous function here, like this:
setInterval(function() {
DisplayTime(currentTime, $('.answer-body'));
}, 1000);
Don't ever pass a string to setInterval() or setTimeout() if you can avoid it, it performs an eval() and has scope issues, like the one you're currently experiencing, since currentTime isn't a global variable.
$(document).ready(function () {
var currentTime = new Date('3/09/2010 9:27:29 PM');
var destination = $('.answer-body');
function DisplayTime()
{
destination.html(currentTime);
currentTime.setTime(currentTime.getTime() + 1000);
}
var id = setInterval(DisplayTime, 1000);
})
This uses a function (closure) within a function, but not an anonymous one. DisplayTime will not be accessible from outside scopes. There's no real reason to dislike anonymous functions, used appropriately. I would use one here.

In JavaScript, does it make a difference if I call a function with parentheses?

I noticed a difference when calling a function with empty parentheses, or without any parentheses at all. However, I am not passing any arguments to the function so I wondered, what would be the difference between:
window.onload = initAll();
and
window.onload = initAll;
Please explain the principle behind it.
window.onload = initAll();
This executes initAll() straight away and assigns the function's return value to window.onload. This is usually not what you want. initAll() would have to return a function for this to make sense.
window.onload = initAll;
this assigns the actual function to window.onload - this is possible because in JavaScript, as #Felix says, functions are first class objects - without executing it. initAll will be executed by the load event.
You may also see something like this:
window.onload = () => initAll();
This will create a new function that, when called, will call initAll immediately. Parentheses are necessary here for that "call initAll immediately" part to work. But, because it's wrapped in a function, nothing will execute until that outer function itself is called, and you assign the reference of that outer function to window.onload, so initAll will also be executed on the load event.
What Pekka says is correct, but I want to elaborate a little with an example that will help explain to someone who doesn't fully understand function pointers or delegates.
I won't use window.onload because that's a bit contrived to demonstrate. I'll use a simple multiply function to demo instead:
function Multiply(operator, operand) {
return operator * operand;
}
This could equally be written:
Multiply = function(operator, operand) {
return operator * operand;
}
While in the first example, the implication may not be obvious, the second example shows more clearly that we're assigning a function which has 2 parameters to a variable called Multiply, and this concept of functions as assignments is common throughout JavaScript. This is a small demonstration of the fact that functions are "first class citizens", that is, they can be passed around exactly as if we were passing around values.
So now to the difference of assignment:
var operator = 3;
var operand = 4;
var ret = Multiply(operator, operand);
At the point of defining the ret variable, Multiply is executed and the return value is assigned - ret becomes equal to 12.
Let's try that again a different way:
var operator = 3;
var operand = 4;
var ret = Multiply;
Now, at the point of defining ret, ret becomes your Multiply function as opposed to being the result obtained from your Multiply function. Calls to ret() will cause your Multiply function to be executed, and you can call it exactly as if you'd called Multiply(operator, operand):
var out = ret(3, 4);
is the same as
var out = Multiply(3, 4);
You have effectively said that you are going to use ret as a delegate for Multiply(). When calling ret, we're really referring to the Multiply function.
Back to your window.onload. Think of this as:
window.onload = function() {
//Doing what all good window.onload functions should do...
}
initAll = function() {
return 12;
}
So as you can see, window.onload is a function just like any other function, there's nothing special about it. You can assign it a value, assign it a function, null it out if you wish - the point is that there's nothing any more special about window.onload than there is about your own function. The only slightly different thing is that it gets called by the window when it's loaded. [Disclaimer: I've never actually nulled out window functions, so I'm not sure if this will cause negative repercussions. One would hope they check to see if a function is assigned before calling it i.e. if (window.onload) window.onload();].
Now calling initAll() what we're saying is:
window.onload = initAll();
which might as well say:
window.onload = 12;
But when we say initAll without the parentheses, what we're really saying is: I want to replace whatever my window.onload function is, with a new function - i.e. I want to replace it with my initAll function, so that any calls to window.onload runs my initAll code.
So:
window.onload = function() {
//Doing what all good window.onload functions should do...
}
is replaced with:
window.onload = function() {
return 12;
}
So any call to window.onload will execute your initAll function instead of whatever window.onload was originally. You have replaced the original function with your new function.
In fact, you could equally write:
window.onload = function() {
//Write all your init code right in here instead of having a separate
//initAll function.
}
Another example that may demonstrate better is this:
var d = new Date();
var currentTime = d.getTime();
Whatever the time was at the time d is defined ends up assigned to currentTime. Great, but that's only useful if we want to find out what time the function containing that code was called - i.e. at page load time. What if we want the current time any time that currentTime is called?
var currentTime = function() {
var d = new Date();
return d.getTime();
}
var a = currentTime(); //The current time at the point a is defined...
var b = currentTime; //b is a functional reference to currentTime...
var c = b(); //The current time when variable c is defined
var d = c; //The current time when variable c was defined
Notice how we call b() in our c and d assignments exactly as we could call currentTime()?
Functions in javascript are first-class citizens, and as such, can be assigned to other variables or passed around as arguments.
So, when you do
window.onload = initAll;
You are setting the onload property of the window object to reference the initAll function itself.
When you do
window.onload = initAll();
You are setting the onload property to hold the return value of initAll, since it will execute in place on that line.
I'm 6 years late but I feel this could have been explained a lot simpler than the above answers.
So here is the TLDR; or bird's eye view when calling functions using and not using ()'s
Lets take this function for example:
function foo(){
return 123;
}
if you log "foo" - without ()
console.log(foo);
---outout------
function foo(){
return 123;
}
Using no () means to fetch the function itself. You would do this if you want it to be passed along as a callback.
if you log "foo()" - with ()
console.log(foo());
-----output-----
123
Using () after a function means to execute the function and return it's value.
initAll is a reference to a function value and the brackets operator appended to the function name RUNS this function object.
So if you do something like
a = initAll
then a will become the same as initAll - for example you can do a() - but with
a = initAll()
the variable a will get the return value of the executed initAll function

Categories

Resources