why the function call does not work this way? - javascript

This is the script that i tested when the page loads.
window.onload = initAll;
function initAll() {
document.getElementById("pTag").innerHTML = "Hello Java Script !";
}
The above script works fine till i put parenthesis like initAll() during the call. _( window.onload=initAll(); )_ . Nothing happens if use initAll() during function call. It is like the script wasn't there.
Why is it so ?

window.onload expects the value you set for it to be a function (functions are like any other object in JavaScript).
If you put parens after initAll, you actually invoke the function and set window.onload to the function's return value. Since the function does not return anything explicitly, this value is undefined. So in practice you can think of this code:
window.onload = initAll();
function initAll() {
// do something with document
}
as equivalent to this code:
var result = initAll();
window.onload = result;
function initAll() {
return null;
}
I 'm sure you can immediately see why this would not work.

Because you should not execute the function at that line, you should assign an event handler to the window object, which will be triggered/executed once the load event has fired, not the returned value of a function.
However, assigning an event handler window.onload is not recommended, because it will allow for only one handler to be attached. Consider using addEventListener.

Because you're not calling the function directly in the window.onload statement, but you're assigning a function to the onload event. The system will then automatically call your initall function when the event happens. Thats why you need the function itself (without parenthesis), and not the call (with parenthesis)

This has to do with the way Javascript works. Functions also are actually objects, like about everything in javascript.
So basically, you are assigning the "Object" initAll , which happens to be a function, to window.onload . This object is then called when the onload event is triggered, assuming it is a function.
Now, when you are putting parenthesis behind your objects name, you are basically telling it to treat that object like a function and call it. this is not the way how to assign it to a property, like the window.onload property.

window.onload = initAll;
You're binding the initAll function to the onload event of the window object. The function becomes the load handler. Now, when the load event fires at the window object, this function will be invoked.
window.onload = initAll();
You're immediately invoking the function initAll. this invocation returns undefined (in your case), and that undefined value will be assigned to window.onload. Assigning the undefined value to onevent properties obviously has no effect.

When you omit the parentheses in this call:
window.onload = initAll;
You are assigning to the window.onload event the reference value of the function initAll(). This causes the function to execute when the onload event is called because they share the same reference point. When you use the assignment like this:
window.onload = initAll();
You are assigning to the window.onload event the returned value of the function, which in this case is null.

Related

jQuery `this` scope issue

I have a global function defined in one place:
function addToCart (){
var prodText = $(this).parent().siblings(".item1").text();
$("#"+prodId+"shopC").children(".item1").text(prodText);
alert(prodText);
}
Then, I want to call it inside a HTML element with an inline onClick event:
onClick='addToCart()'
It is not working, but it works if I put the function code directly inside the onClick event, so that must be a this scope issue.
There are many questions/explanations about this scope but I must confess I miss a simple straight answer for this specific case (I tried to use "use strict" with success either).
How to make this work?
As per current implementation this doesn't refers to the element which invoked the function. It refers to window object.
You need to pass the current element context i.e. this to the function as
onClick='addToCart(this)'
and modify the function to accept element as parameter.
function addToCart (elem){
var prodText = $(elem).parent().siblings(".item1").text();
$("#"+prodId+"shopC").children(".item1").text(prodText);
alert(prodText);
}
Basically this inside a plain function will point to window. you have to pass the this context to the inline handler onClick='addToCart(this)'. Receive it and use it inside of event handler like below.
function addToCart (_this){
var prodText = $(_this).parent().siblings(".item1").text();
you have to pass this keyword where you inline calling the addToCart function then you can capture that element
onClick='addToCart(this)'
this object in your function does not point to the object where you added the onClick function to. It rather points to the window object.
You need to pass this as a param to your function.
function addToCart (trigger) { // Code goes here }
and call addToCart(this) in your onClick.
Learn more about this in javascript here.

onclick assigned function with parameters

I'm not sure if this has been asked before because I don't know what it's called.
But why wouldn't a method like this work? Below is just a general example
<script>
document.getElementById('main_div').onclick=clickie(argument1,argument2);
function clickie(parameter1,parameter2){
//code here
}
</script>
The code above would work fine if the event handler was assigned without parameters, but with parameters, it doesn't work. I think I read online that to overcome this problem, you could use closures. I'm assuming it's because of the parentheses ( ) that is calling the function immediately instead of assigning it to the event?
Because you're calling the function immediately and returning the result, not referencing it.
When adding the parenthesis you call the function and pass the result back to onclick
document.getElementById('main_div').onclick = clickie(); // returns undefined
so it's actually equal to writing
document.getElementById('main_div').onclick = undefined;
which is not what you want, you want
document.getElementById('main_div').onclick = clickie;
but then you can't pass arguments, so to do that you could use an anonymous function as well
document.getElementById('main_div').onclick = function() {
clickie(argument1,argument2);
}
or use bind
document.getElementById('main_div').onclick = yourFunc.bind(this, [argument1, argument2]);
It is however generally better to use addEventListener to attach event listeners, but the same principle applies, it's either (without arguments)
document.getElementById('main_div').addEventListener('click', clickie, false);
or bind or the anonymous function to pass arguments etc.
document.getElementById('main_div').addEventListener('click', function() {
clickie(argument1,argument2);
}, false);
The easiest way is:
yourElement.onclick = yourFunc.bind(this, [arg1, arg2]);
function yourFunc (args, event) {
// here you can work with you array of the arguments 'args'
}
When you say onClick = function() {...} you are registering your function with some internal JavaScript library. So when the "click" happens, that library invokes your function.
Now imagine you're the author of that library and someone registered their function with it. How would you know how many parameters to pass to the function? How would you know know what kind of parameters to pass in?
clickie(argument1,argument2)
This means to invoke the function and return its return value.
clickie
This simply is a reference to the function (doesn't invoke/execute it)
To bind an event to a element, you need to use either the attachEvent or addEventListener method. For example.
/* Non IE*/
document.getElementById('main_div').addEventListener('click', function () {}, false);
/* IE */
document.getElementById('main_div').attachEvent('onclick', function () {});
A function name followed by parentheses is interpreted as a function call or the start of a function declaration. The a onclick property needs to be set to a function object. A function declaration is a statement, and is not itself a function. It doesn't return a reference to the function. Instead it has the side effect of creating a variable in the global scope that refers to a new function object.
function clickie(param) { return true; }
creates a global variable named clickie that refers to a function object. One could then assign that object as an event handler like so: element.onclick = clickie;. An anonymous function declaration (often confused with a closure; for the difference see Closure vs Anonymous function (difference?)) does return a function object and can be assigned to a property as an event handler, as follows:
element.onclick = function(event) { return true; };
But this doesn't work:
element.onclick = function clickie(event) { return true;};
Why? Because function clickie(event) { return true;} is a statement, not a function. It doesn't return anything. So there is nothing to be assigned to the onclick property. Hope this helps.

javascript passing event in closure

I was trying the following:
f.addEventListener('submit',(function(frm){
var func = (function(e){somefunction(e,frm);})(e);
})(f),false);
But this is failing. I want to pass the form (f) as a static reference and the dynamic event object to the named function 'somefunction'.
What I have above isnt working, what is the right syntax for passing both?
The issue is that each of the functions is being called right away, with undefined actually being passed to addEventListener().
You'll want to instead return one of the functions without its calling parenthesis so the event can call it later:
f.addEventListener('submit', (function (frm) {
return function (e) {
someFunction(e, frm);
};
})(f), false);
Though, with event bindings, you may not necessarily need the closure, as the <form> will be the context (this) of the function passed:
f.addEventListener('submit', someFunction, false);
function someFunction(e) {
var frm = this;
// ...
}
not saure exactly what you are trying to do but, to looks like you are trying to manually pass in the form via the event handler. Instead save a reference and just refer to it in the handler such as
f.addEventListener('submit',function(){
var func = function(e){
somefunction(e,f);
};
},false);
you shouldn't need the self executing functions unless I am missing your intent here

Why does a Javascript function call not contain '()' after the name of the function?

window.onload = function() {
document.getElementById('clickMe').onclick = runTheExample;
}
function runTheExample() {
alert('running the example');
}
This is a simple event handler for the onclick event for an html input button with id = clickMe.
In line 2, why is the call to function runTheExample not immediately followed by ()? I thought that to call a function you must pass it any variables/objects it expects in an open/close parenthesis, and if the function isn't expecting anything, you must still include the open and close parenthesis like runTheExample().
document.getElementById('clickMe').onclick = runTheExample;
The intention here is not to call runTheExample() but to assign the reference to the function runTheExample to the onclick event.
Internally, when the onclick event is fired, Javascript is able to call the function runTheExample through the reference you provided on the code above.
Snippet
var myFunction = function() { return 42; };
// Assigning the reference
myObject.callback = myFunction;
myObject.callback(); // Has the same effect as calling myFunction();
// Assigning by calling the function
myObject.callback = myFunction();
myObject.callback; // Returns 42
myObject.callback(); // Exception! Cannot call "42();"
That's not Javascript-specific. Passing functions by reference is available in many languages.
You use the parenthesis only to invoke (call) a function. When you're assigning it to onclick, you're merely passing it by reference.
To better understand this, think about the other method of declaring a function:
var runTheExample = function () {
alert('running the example');
}
Regardless of what method you use, runTheExample will contain a reference to the function (there are some differences, like the function reference not being available before assignment, but that's a different story).
Functions are objects in javascript. That line sets the onclick property of the click me element to the runTheExample function, it doesn't call that function right then.
var a =runTheExample; //sets a to runTheExample
a(); //runs the runTheExample function
So when the function name is referenced without the () it is referring to the function object, when you add the () it is a call to the function, and the function executes.
It's not calling it, but rather setting the property onclick. When a call is made to onclick(), it will then run the function you've defined. Note however that the context of this will be the object that calls it (document.getElementById('clickMe')).
You're not calling the function here. You're setting the function as an event handler, and the function is not actually called called until the event is fired. What you've written references the function; that's a different notion than actually calling it.
In this case, the runTheExample function is being treated as a variable and being assigned to the onclick event handler. You use () after a function name to call a function. If you added them here, what would happen is that runTheExample() would be called once during load, showing an alert, and then a null value would be assigned to the onclick handler.
Because it binds runTheExample to onclick event.
When you add () it triggers the function.

Passing a function pointer to an event in JavaScript

I understand when passing a function pointer to an event handler you cannot invoke the function block with parentheses or the return value of that function will be assigned to the event handler. I tried this and I'm confused on how it works?
window.onload = alert("Hello, World.");
I can see how this works:
window.onload = function () { alert("Hello, World!"); };
The literal function is not self-invoked leading to no return value and is only invoked once the onclick-event is invoked.
Edit 1: I don't want to achieve anything with this. I just want to understand how window.onload = alert("Hello, World."); works perfectly and how window.onload = show_message("Hello, World."); doesn't work?... Considering that show_message is actually a function.
Edit 2: Some user is claiming the onload event handler to work with parentheses on any function. I do not think this works like it should because the function is invoked ignoring the event handler and the return value of that function is assigned to the event handler. Most functions do not return anything so (undefined or null) will be assigned to the event handler.
Look at the code below:
var button = document.getElementById("button");
function test() {
str = "works";
console.log(str);
}
button.onclick = test;​
Assume there is a button element with the id of button assigned to it. This will only work if test is not invoked with parentheses (button.onclick = test();). Test will only run once and undefined will be assigned to onclick.
Edit 3: It looks like a return value is not assigned to an event handler if the function is invoked. It always writes out null to the console when I use console.log.
Nice question. Actually it does not work as you expect it to work. It's just illusion that it works that way. When you run:
window.onload = alert("Hello, World.");
The right part of the statement is executed and alert is shown, but the window on load handler is not set up to some function, null will be assigned to it, since this is what alert returns.
By the way even if you call the method with parentheses you can return function from it to assign to the event handler:
var button = document.getElementById("button");
function test() {
str = "works";
console.log(str);
return function(){console.log('button clicked');}
}
button.onclick = test();
window.onload = alert("Hello, World.");, you saw the alert works just because it alert when it execute, and assign the result (undefined) to window.onload.

Categories

Resources