Call JS function with brackets - javascript

for my own personal improvement, I was fiddling with closures and functions in JS, when I found this behaviour that deeply puzzles me.
Take this function, assign it to a variable, and call it from two different HTML elements via jQuery:
var print = function(){
console.log("Hello" );
};
document.getElementById('element1').onclick = print();
document.getElementById('element1').onclick = print;
Why on earth is the second element, if clicked, to be the one that prints correctly "hello"?
I always thought you need to put brackets after a function's name to call it.
In fact, if I just call the function by itself (and not via a jQuery event) it works as expected:
var print = function(){
console.log("Hello" );
};
print; //does nothing
print() //prints "Hello"
What I am missing here? Is something related to jQuery?
Thanks in advance!

The difference is calling a function vs taking a reference to a function.
The syntax func() immediately calls the function provided. In element.onclick = func(), the event will be bound to the return value of func.
With element.onclick = func, you are not calling func, simply referencing it and assigning it to the event.
If func happened to return a function, then you could use the element.onclick = func() syntax, and it would do what you expect.
document.getElementById('element1').onclick = print(); // Assigns the *return value* of print
document.getElementById('element1').onclick = print; // Assigns print
function returnPrinter() {
return function print() {
// do stuff
}
}
document.getElementById('element1').onclick = returnPrinter(); // Assigns the return value, which is a function, thus doing what you want

(Too long for comment.)
If you really want to mess with your own head:
var print = function() {
return function() {
console.log("Hello");
};
};
document.getElementById('element1').onclick = print();
This will do what you expect, but perhaps not why you expect it to.

Using
document.getElementById('element1').onclick = print();
is equivalent to the value returned from print (but there is no returned value, so it is undefined)
document.getElementById('element1').onclick = undefined;
When the onclick event handler is called, it calls the assigned value expecting a function. undefined() will also give you the same error. print() will do what you were expecting, and that is why when you use this it works
document.getElementById('element1').onclick = print;

A function is just like any other variable, except it has an additional operator:
Just like with objects and arrays, you can use the dot and square-brace operators to retrieve their properties, you can use the call operator to call the function, but that function is still a variable nevertheless.
function a() {
console.log("potato");
}
var b = a;
b() //prints "potato" on the console
On your example, using the print function on its own (without the call operator did nothing, but that would be the same as if you wrote a number on its own: the result is the value itself!
console.log(a); //prints function a()
console.log(42); //prints 42
When you type a something on its own line, it's just going to return that value to the expression, but without anything to do, nothing happens:
a; //nothing happens
42; //nothing happens
Now, when you use the call operator, it runs your function and the expression's value is whatever the function returned, or undefined if it didn't return anything.
function doStuff() {
return "potato";
}
Now suppose you have this expression:
console.log(doStuff());
It will run doStuff, and return to the expression:
console.log("potato");
Then it will run console.log, with "potato" as its parameter, and it will do its magic to show on the console.
Events are just like that, saving a function to a variable to use later:
function doom() {
return Infinity / 0;
}
onDoomsday = doom;
//somewhere else in your code:
onDoomsday(); //destroys the world

you have to bind reference of a function to onclick but in first case you actually doing nothing other than calling a function:
document.getElementById('element1').onclick = print();
It will actually invoke the function print() and since function has nothing in return so it will not impact on element1 click event.
on the other hand
document.getElementById('element1').onclick = print;
In order to make first case working you need to return a function so it can be invoked on event:
var print = function() {
// when this will invoke it will return function
return function() {
console.log("Hello");
};
};
will assign reference of function to onclick event and it invoke the function on each click event.

Related

Why can't I access a returned function with the dot syntax

I though that once createFunction runs I'll have access to the inner function.
function createFunction() {
function printHello() {
return console.log("hello");
}
return printHello;
}
// Both of these return undefined
createFunction(printHello());
createFunction.printHello();
Any thoughts?
Proper syntax is:
createFunction()();
... or, a bit more wordy:
const returnedFunction = createFunction();
returnedFunction();
... as printHello name makes any sense only within createFunction, but its value is actually returned by that function. And yes, it's perfectly ok to place any number of () in sequence you want.
As a sidenote, returning the result of console.log('hello') makes little sense: logging itself is a side effect, no need to check its result.
I though that once createFunction runs I'll have access to the inner function.
No, you cannot access a variable that is inside of a function outside of it. If you call a function those variables exist, but you cannot access them. However if a value gets returned, you can work with the function call as if it would be that expression. In your case you return the function so you can access it as:
var print = createFunction();
print();
Or as a oneliner:
createFunction()();
In your code createFunction returns another function, so to execute inner function you must call inner function by appending () after return value of createFunction i.e createFunction()();
createFunction() give printHello = function definition
createFunction() () same as printHello**()**
Also if we simplify your code we can re-write as
function printHello() {
console.log("hello");
};
function createFunction() {
return printHello;
};
console.log("return value of: createFunction()");
console.log(createFunction());
console.log("return value of: createFunction() () --> printHello()");
createFunction()();

In a closure, why does the main variable not get reset every time it is called?

I'm trying to get a solid understanding of closures, and I'm struggling with the mechanics of it. I've looked on w3schools (https://www.w3schools.com/js/js_function_closures.asp) and MDN (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures) and a few other places. I understand what a closure is and how to make it work but I don't understand why subsequent calls after the first call to the outer function just seem to go straight to the inner one instead.
Here is my code - a simple, working closure:
var add = (function () {
var a = 0;
alert('hi');
function addInner(){
a += 1;
return a;
}
return addInner;
})();
function getAdd() {
document.getElementById("test").innerHTML = add();
}
I have two questions that probably both have the same answer: Why does a not get reset every time I call add()? And why does the alert not pop up except for on the first time?
I attached getAdd() to a button, and it works great, but it but doesn't pop up with the alert past the first time. Why does it do this?
Edit: I also found the first answer to this question (Why Don't Variables Reset in a Closure (Javascript)) really helpful.
add is a reference to addInner, not the anonymous "outer" function, since the "outer" function returns addInner. Then, you call that anonymous function once - that last set of ()- and store the resulting function, with its own private 'a', in add.
Imagine that the outer function was a named function called constructAdder, and you called
var add = constructAdder();
var add2 = constructAdder();
That's basically what you've done, but with an anonymous function, if that makes it any clearer. You have an outer function that constructs an inner function that can count, due to the magic of closures.
Those questions do both have the same answer. And it's fairly simple. This statement:
var val = (function() {
return 42
}())
sets val to 42. Not a function. This is called an IIFE, or immediately-invoked function expression. We are declaring a function and calling it immediately. We never save that function. We just use it once to get the value it returns:
val // 42
Contrast that to:
var val = function() {
return 42
}
In this case we set val to a function that, when called, returns 42.
val() // 42
val() // 42
We can get pretty crazy with IIFEs:
var val = (function() {
return (function() {
return (function() {
return 42
}())
}())
}())
The value returned by that mess is still 42.
val // 42
All those functions are declared once, used once, and thrown away. But IIFEs are capable of so much more:
var add = (function() {
var counter = 0
return function() {
return counter++
}
}())
We're now using the IIFE to create a private variable! counter cannot be accessed outside the scope of the IIFE. It's safe. But the inner function can access and modify it. It's a fully encapsulated, stateful function!
add() // 0
add() // 1
counter // Uncaught ReferenceError: counter is not defined
This is what your code is doing:
var add = (function () {
var a = 0;
alert('hi');
function addInner(){
a += 1;
return a;
}
return addInner;
})();
It is encapsulating the a variable so that it cannot be accessed outside the scope of the IIFE. The addInner function, however, does have access to a and can modify it at will.
The alert() is only called once because that IIFE is only called once, then thrown away. Note that the function itself is the only thing thrown away. Since addInner maintains a reference to the scope (closure) created by the IIFE, that scope is safe from garbage collection.
In fact, that's a helpful way to think about IIFEs:
var val = function() {}
creates a function and
val()
creates a closure (the context that the function's body runs in). IIFEs are used when we don't care about the function, we just want the closure it creates.
Hope this helps. Have fun out there!
var add = (function () {
var a = 0;
alert('hi');
function addInner(){
a += 1;
return a;
}
return addInner;
})(); <-- This
The () at the end means that add is added forever, and if you look at the line above, then it says return addInner. This means that add() is actually addInner(), the good thing with this is that addInner has access to a. Actually writing the function like this is more proper.
var add = (function () {
this.a = 0;
alert('hi');
var addInner = function(){
this.a += 1;
return this.a;
}.bind(this);
return addInner;
})();
Because now you would think that add.a would make a available because it is written as this.a, but since addInner is returned, then it is not available.
You should focus on the
(function(){
// impl
})()
block.
It is called an Immediately Invoked Function Expression or IIFE.MDN reference
So when the code executes to line 1, it first evaluate the right side and the IIFE returns a closure which was then assigned to the variable add. Meanwhile, an alert was invoked in the IIFE. Understanding the IIFE can help you solve the problems.
In my opinion , the key is IIFE, after the code below is executed at the first time,
var add = (function () {
var a = 0;
alert('hi');
function addInner(){
a += 1;
return a;
}
return addInner;
})();
(Look out ! There is no add() in the code above because IIFE will be Invoked Immediately and the return addInner finished the initialization of variable add )
the function add has been changed to :
add = function addInner() {
a += 1;
return a;
}
Of course, the alert() only executed one time because the add has been changed at the begining.
Why does a not get reset every time I call add()?
And why does the alert not pop up except for on the first time?
that is the answer of your question.
variable a didn't destroy because the function add still have a reference, and this is about the closure.

Binding function to another function in object

I try to bind a function but I dont really know how its work
For example
q={};
q.e=function(){return 1;}
q.e.i=function(){alert(this);}
q.e().i(); //Nothing happend I excepted that it will alert 1
So how does it work?
Thank you.
A function does also inherit from Object in Javascript. Hence you can assign properties to a function object, which you're just doing by calling
q.e.i = function() {};
but thats it. If you want to call it, you need to the same semantics
q.e.i();
in your current snippet, you're trying to execute .i() on the return value of e(), which happens to be the number 1.
You should be getting an error when calling q.e().i(); q.e() == 1 so (1).i() is an error since the Number object doesn't have an i method.
Hard to help since the code doesn't make any sense. I can only say that what you expected doesn't make sense in my head :)
Here's some code that would do what you expect
var q = {};
q.e = function() { return 1; };
q.e.i = function() { alert(this); }
// Call q.e.i, specifying what to use as this
q.e.i.call(q.e());
The trick is that in JS, this changes depending on how you call the function.
function a() {
console.log(this);
}
var obj = {
method: a
};
// Outputs the window object, calling a function without a `.` passes
// The window object as `this`
a();
// Outputs the obj, when you say obj.method(), method is called with obj as `this`
obj.method();
// You can also force the this parameter (to the number 1 in this case)
// outputs 1
obj.method.call(1);

return a value from object in js

Assume I have a simple object in js with one private variable:
function test(){
var value=true;
}
and now I want to create one instance:
var r=new test() //I want to get r === true
How can I return a value from it?
If I write:
function test(){
var value=true;
return value;
}
I have a test {} in result.
If I write:
function test(){
var value=true;
return function(){ return value; }
}
then I can get the value, but I must add additional parentheses:
var r=new test()() //r === true
I don't want the parentheses, so I tried to change the code to:
function test(){
var value=true;
return (function(){ return value; } )();
}
But in response, again I get test {}
How to write the return statement in this situation?
I believe you need to do something like:
function test(){
this.value = true;
}
and then
var r=new test();
if (r.value == true) {
//Do something
}
First I feel obliged to clarify a possible misunderstanding:
function test(){
var value=true;
}
is not an object with a private variable. It is a function with a local variable. When you call the function with new, it creates an object inheriting from the functions's prototype with no properties. If you call the function normally, it simply executes the function body and returns undefined (since you are not returning anything).
Solutions:
Do you actually need a constructor function? I'm asking because your example is very simple. Obviously you cannot have the function return two values, true and the object.
So, you could just call the function without new:
function test() {
var value = true;
return value;
}
var r = test();
If you really want r to be true then I see no reason to call the function as a constructor function.
The reason why you got test {} as result was because you called the function with new. If you do that, the function will always return an object and if you don't do so explicitly (value is a boolean, not an object), it implicitly returns this (which is an object).
So again, if you really want r to be equal to value from inside the function, then simply don't call the function with new.
If you need an object though, there are a couple of ways:
You can assign the value to a property and access it instead, like PokeHerOne showed in his answer or add a function which returns that value, as papaiatis demonstrates. The advantage is that the value is accessed explicitly and other people looking at your code understand what's going on.
Additionally, depending on what you want to do with that value / object, you can implement the valueOf methods, which gets called by various operators.
For example:
function Test(){
var value = true;
this.valueOf = function() {
return value;
}
}
var t = new Test();
console.log(t); // logs the Test instance
console.log(t == true); // logs `true`
I.e. t is an object but behaves like the value true (value) in various operations. This is powerful but can also be quite confusing, since the type conversion is somewhat implicit and it's not something that is used in JavaScript very often.
Used methods defined internally:
function TestClass(){
var value = true;
this.getValue = function(){
return value;
};
}
var t = new TestClass();
alert(t.getValue()); // true
Since value is defined as private it is not accessible from outside:
alert(t.value) // undefined

Very basic Javascript constructors problem

In the following JavaScript code main() is called.
My question is why the second constructor is called rather than the first one ?
What am I missing here ?
Thanks !!
function AllInputs() {
alert("cons 1");
this.radioInputs = [];
alert(this);
}
function AllInputs(radioElement) {
alert("cons 2");
this.radioInputs = [radioElement];
alert(this);
}
AllInputs.prototype.toString = function() {
return "[object AllInputs: radioInputs: " + this.radioInputs.length + "]";
}
function main() {
var result = new AllInputs();
}
Javascript does not support overloaded functions.
When you define the same function twice, the second definition replaces the first one.
Instead, you should make a single function, and check arguments.length to see how many arguments were passed.
For example:
function AllInputs(radioElement) {
this.radioInputs = arguments.length ? [radioElement] : [];
alert(this);
}
In JavaScript, the last definition of an identifier is used:
function foo() { return "bar"; }
var foo = "foo";
alert(foo);
In that case, foo was a variable with the value "foo". Had foo been a function, it would have simply said that foo was a function. If you don't believe it, try using alert(foo()) instead of just alert(foo). You'll most likely get an error in your console log with no visible output like you had with alert(foo) (the variable...not the function call).
function foo() { ... }
is really just shorthand for
var foo = function () { ... }
Hence, the second time you're declaring the function, you're overwriting the variable AllInputs with a different function. There ain't no such thing as two functions with the same name in Javascript, since all functions are really variables.

Categories