Why we're not use () at window.onload? - javascript

At end of this code (full code is here)
function addSongs() {
var song1 = document.getElementById("song1");
var song2 = document.getElementById("song2");
var song3 = document.getElementById("song3");
song1.innerHTML = "Blue Suede Strings, by Elvis Pagely";
song2.innerHTML = "Great Objects on Fire, by Jerry JSON Lewis";
song3.innerHTML = "I Code the Line, by Johnny JavaScript";
}
window.onload = addSongs;
You will see addSongs didn't used with ().
If i change it as
window.onload = addSongs();
It doesn't works. Why?

when you have addSongs(), it's telling Javascript immediately execute that function and assign the return value of that call to the onload handler.
Without the (), it tells the JS engine to assign the function itself to onload.
e.g. if you had something like
function x() {
return 'hello';
}
// immediately assigns "hello" to the onload
window.onload = x();
which is the same as doing
window.onload = 'hello';
and at some point the JS engine will try to execute a function named "hello", whenever the onload handler is triggered.

addSongs is a function, which you can assign to a variable (namely, in this case, window.onload). On the other hand, addSongs() is calling that function, and therefore you're setting window.onload to whatever addSongs() returns. Which is nothing, in this case.

just like we assign int a = 5;
cuz we now know that a is an int and we can assign it a integer value like
similarly window.onload is a function , u can consider it to be of function type datatype
thus we can assign
window.onload=function(){ .. some code ... }
or we can use
function abc(){ ... some code ...}
window.onload=abc;

When you use addSongs() it executes it right away instead of when it is being called.

Because you're setting onload to be equal to the function.
If you call the function, then you're setting onload to be equal to the return value of the function (in this case, undefined).
Also, you have no control over when onload/onready/onclick/etc fire. That's the point.
You're asking the browser to fire the function when one of those things happen -- not before.

Related

Simple question about using functions and invoking them

Pretty basic question, but I'm not able to find a suitable answer anywhere as I'm not sure what verbiage to use. I'm trying to better understand what is happening here so I can keep myself from making this mistake again. As you can see on the last line, I'm trying to set the onclick event, but it immediately invokes the function. The solution is to remove the parenthesis, but what exactly is that doing? What is the difference between the two? Thanks for any help.
let element = document.querySelector("button");
function turnButtonRed (){
element.style.backgroundColor = "red";
element.style.color = "white";
element.innerHTML = "Red Button";
}
element.onclick = turnButtonRed();
think of turnButtonRed as a variable.
var turnButtonRed = function(){ return 2 };
Now, if you use that variable to pass it to onclick, for example, you have 2 possibilities
element.onclick = turnButtonRed; // this is setting onclick to a function
element.onclick = turnButtonRed(); // this is setting onclick to whatever the function returns (2 in this case).
You want onclick to be set to a function, not the result of a function. turnButtonRed() gives you the result of the function, turnButtonRed is the function itself.
In the statement element.onclick = turnButtonRed(); you are assigning the result of calling turnButtonRed, not that function itself. Simply remove the ().
Here is why. I refer you to the mighty Table of Operator Precedence!
Your line of code has two operators, assignment and function call. Let's see:
Function call is 20
Assignment is 3
We do things in operator precedence order, from highest to lowest. So what is happening is, you are evaluating the function call turnButtonRed() first, then assigning that result to the handler. Which isn't what you want.
Just remove the function call, and assign the function:
element.onclick = turnButtonRed;
Here, we are not calling the function. Instead we assign the function itself as an event handler.
Now, the preferred, modern way of doing this is to add an event handler:
element.addEventListener("click", turnButtonRed);
I leave it as an exercise to the reader to explore why this might be preferred.

Attempting to generate HTML in vanilla JS using document.write, then access the tags using .getElementById [duplicate]

I need to run a javascript function each 10 seconds.
I understand the syntax must work like follow but I am not getting any success:
function funcName() {
alert("test");
}
var func = funcName();
var run = setInterval("func",10000)
But this isn't working. Any help?
A lot of other answers are focusing on a pattern that does work, but their explanations aren't really very thorough as to why your current code doesn't work.
Your code, for reference:
function funcName() {
alert("test");
}
var func = funcName();
var run = setInterval("func",10000)
Let's break this up into chunks. Your function funcName is fine. Note that when you call funcName (in other words, you run it) you will be alerting "test". But notice that funcName() -- the parentheses mean to "call" or "run" the function -- doesn't actually return a value. When a function doesn't have a return value, it defaults to a value known as undefined.
When you call a function, you append its argument list to the end in parentheses. When you don't have any arguments to pass the function, you just add empty parentheses, like funcName(). But when you want to refer to the function itself, and not call it, you don't need the parentheses because the parentheses indicate to run it.
So, when you say:
var func = funcName();
You are actually declaring a variable func that has a value of funcName(). But notice the parentheses. funcName() is actually the return value of funcName. As I said above, since funcName doesn't actually return any value, it defaults to undefined. So, in other words, your variable func actually will have the value undefined.
Then you have this line:
var run = setInterval("func",10000)
The function setInterval takes two arguments. The first is the function to be ran every so often, and the second is the number of milliseconds between each time the function is ran.
However, the first argument really should be a function, not a string. If it is a string, then the JavaScript engine will use eval on that string instead. So, in other words, your setInterval is running the following JavaScript code:
func
// 10 seconds later....
func
// and so on
However, func is just a variable (with the value undefined, but that's sort of irrelevant). So every ten seconds, the JS engine evaluates the variable func and returns undefined. But this doesn't really do anything. I mean, it technically is being evaluated every 10 seconds, but you're not going to see any effects from that.
The solution is to give setInterval a function to run instead of a string. So, in this case:
var run = setInterval(funcName, 10000);
Notice that I didn't give it func. This is because func is not a function in your code; it's the value undefined, because you assigned it funcName(). Like I said above, funcName() will call the function funcName and return the return value of the function. Since funcName doesn't return anything, this defaults to undefined. I know I've said that several times now, but it really is a very important concept: when you see funcName(), you should think "the return value of funcName". When you want to refer to a function itself, like a separate entity, you should leave off the parentheses so you don't call it: funcName.
So, another solution for your code would be:
var func = funcName;
var run = setInterval(func, 10000);
However, that's a bit redundant: why use func instead of funcName?
Or you can stay as true as possible to the original code by modifying two bits:
var func = funcName;
var run = setInterval("func()", 10000);
In this case, the JS engine will evaluate func() every ten seconds. In other words, it will alert "test" every ten seconds. However, as the famous phrase goes, eval is evil, so you should try to avoid it whenever possible.
Another twist on this code is to use an anonymous function. In other words, a function that doesn't have a name -- you just drop it in the code because you don't care what it's called.
setInterval(function () {
alert("test");
}, 10000);
In this case, since I don't care what the function is called, I just leave a generic, unnamed (anonymous) function there.
Change setInterval("func",10000) to either setInterval(funcName, 10000) or setInterval("funcName()",10000). The former is the recommended method.
That's because you should pass a function, not a string:
function funcName() {
alert("test");
}
setInterval(funcName, 10000);
Your code has two problems:
var func = funcName(); calls the function immediately and assigns the return value.
Just "func" is invalid even if you use the bad and deprecated eval-like syntax of setInterval. It would be setInterval("func()", 10000) to call the function eval-like.
Try this:
function funcName() {
alert("test");
}
var run = setInterval(funcName, 10000)
Btw this didn't work
setInterval(function () {
alert("test");
}, 10000);
I had to give a name (whatever you like) to the anonymous function:
setInterval(function alertNotification () {
alert("test");
}, 10000);

Javascript assign variable to alert

I am wondering Can you assign a variable to alert ? what does it really mean and do ? For example,
var a = alert('test');
I tried it out, and the alert pops up as soon as the page loads where variable a remains 'undefined' when I call it. Aren't we suppose to make it an anonymous function with the alert inside like
var a = function(){ alert('test'); }
If we want to trigger an alert on something? Why does javascript allow you to do that?
var a = alert('test');
Think of this statement like any other variable assignment. In order to perform the assignment, first the right-hand side is evaluated. In this case it's a function call, so the function is called and its return value is obtained. In alert's case, the return value is undefined. It doesn't return anything.
Then the return value is assigned to a, so a ends up with the value undefined.
As a side effect of the statement, an alert message is displayed. That happens as a consequence of calling alert() and getting its return value.
function foo(x) {
return x * 2;
}
var a = foo(3);
This code is structurally similar to the alert call, and would result in a being 6. But then alert() doesn't return a value. It's more like this:
function bar(x) {
return;
}
var a = bar(3);
Now a is undefined.
var a = alert('test');
This says to execute alert('test') and assign the return value from that function to a variable named a.
This would be no different than:
var max = Math.max(1,2,3,4);
where max would end up with the value 4 in it as the return value from executing Math.max(1,2,3,4).
var a = function(){ alert('test'); }
This says to declare an anonymous function and assign that function object to the variable a. Since the function is just declared, it is not executed at this time. You can execute it in the future with a().
You commented:
I am just wondering why javascript allows we to do that if it doesn't really means anything
Well, JavaScript (and any other language, including English) allows you to do a lot of stuff that does not mean anything, as long as the syntax is valid. For example, the snippets bellow also mean nothing:
var a;
a = a; // so what?
function something() { /* nothing */ }
var b = something(); // very similar to your example!
Wouldn't it be less consistent if you could assign from some functions, but not from others? If the language were typed, that would produce an error, but since it's not, what's the problem with it? If they don't return a value, their return is undefined, and nothing breaks if you try to assign that to a variable. So you can make functions that sometimes return something, sometimes not. That can be an advantage if used wisely. It's a feature, not a problem with the language.
If you do:
var a = function(){ alert('test'); }
You can then do:
a();
since you've defined an anonymous function..
alert is a function so you can't assign anything to it, per se.
If you want something to pop up if a variable has a value, you could do something like -
$(document).ready(function() {
if (someVar != undefined) {
alert(someVar);
}
});

Dynamically execute a function in JavaScript

I would like to call a function whose name I have in a variable.
For example:
I get the string "pageTracker._trackpageview('/url/page1.page'); " dynamically and assign it to a variable as below
var myFunction = pageTracker._trackpageview('/url/page1.page');";
Now when I submit the page I want to execute the function which is in variable myFunction.
Thank you all.
function functionFromString(funcDef) {
try {
return (new Function("return function() {" + funcDef + "};"))();
} catch (e) {
alert(e);
return (function() {});
}
}
var myFunction = "pageTracker._trackpageview('/url/page1.page');";
var realFunction = functionFromString(myFunction);
realFunction();
Why do it this way?
Just doing eval runs the function right away. If there are errors thrown in the called function itself we can't tell the difference between that and an error in parsing. So by creating a function out of the text, we can separate when we parse it from when we execute it.
Just using newFunction = Function(myFunction) won't compile it, so it's slower. So using new Function() to return a function (that in turn creates a function) is our trick. We could use eval this way, too, but I like new Function better.
What others have said about being really careful with eval (and new Function()) is true. It can be an opening for malicious script.
You can do this with the JavaScript eval() function. Just be careful about controlling the value passed to eval() as it will execute whatever string it is given.
eval("pageTracker._trackpageview('/url/page1.page');");
You are not simply trying to execute a function whose name you have but a complex line of code with a receiver, a method name and a literal string argument. The only way to execute an arbitrary snippet of codes is with eval() But eval() is dangerous. If you're not very careful, someone can pass malignant code to your script that will be executed inside the eval() call.
You can make use of eval in javascript..
var myFunction = "pageTracker._trackpageview('/url/page1.page');";
//...
eval(myFunction);
Solution: Wrap the function
//define:
var myFunction = function (){pageTracker._trackpageview('/url/page1.page');}
//call:
myFunction();
Full Example:
<html>
<head>
<script type="text/javascript">
var foo = function (){alert('bar');}
</script>
</head>
<body onload="foo();"> </body>
</html>
But this way, you cannot check if parameter is correct url, or encode it ect. And I avoid eval as hell for known reasons.
I would prefer the harder, but more safe way - if it is a string, it can be parsed:
//test dub
pageTracker = {
_trackpageview: function(path) {alert(path)}
}
var str = "pageTracker._trackpageview('/url/page1.page')";
//get param
var urlpathregex = /\('([a-z0-9\-._~%!$&'()*+,;=:#\/]+)'\)/;
var param = urlpathregex.exec(str)[1];
//do some stuff/validation with param
[...]
//get object and function name
var funcregex = /([a-zA-Z0-9_]+)?\.?([a-zA-Z0-9_]+)(?=\()/;
var match = funcregex.exec(str);
var obj, func;
obj = match[1];
func = match[2];
//invoke
window[obj][func](param);
This is just an example, and not copy&paste ready code :) Because to begin with - if you get dynamically "pageTracker._trackpageview('/url/page1.page')" as a string, there is some code smell here already.

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