I was playing around with javascript objects to understand "this" and function context better. I stumbled across this problem. I get the error "obj2 is not defined" unless I run window.obj2() after assigning it, but I don't know why. Shouldn't it be enough to assign the function to window.obj2 without also executing it immediately afterwards? I know that you're not supposed to pollute the window object, this is just a test.
Thanks!
window.obj2 = function(){
console.log('obj2 in window.object',this);
}
window.obj2(); // problem when this line is commented out
(function () {
var parent = {
obj : function(){
//console.log(this);
obj2();
this.obj2();
window.obj2();
},
obj2 :function(){
console.log('obj2 in parent',this);
}
}
parent.obj();
}());
EXPLANATION
OP asks why does he have to execute the function after defining it in order for it to become defined later in the code... See what happens when you comment out the problem line.
Solution to the mystery:
You forgot a semicolon:
window.obj2 = function(){
console.log('obj2 in window.object',this);
}; // <--
Without it, the code will be interpreted as
// I'm naming the functions to refer to them later
window.obj2 = function a(){
...
}(function b() { ... }());
I.e. the parenthesis around b are interpreted as call operation of a (just like you did with b itself: (function b() {...}()).
The engine first executes b in order to pass the return value as argument to a, and only after that the return value is assigned to window.obj2.
So, at the moment b is called, window.obj2 does indeed not exist yet.
So, the reason why adding window.obj2() makes it work is not because you are accessing window.obj2, but because it makes the code un-ambigious. The following parenthesis cannot be interpreted as call operation anymore. You could use any statement there, e.g.
window.obj2 = function(){
console.log('obj2 in window.object',this);
}
"foo";
(function () {
obj2();
}());
If you defined function window.obj2 inside the anonymous function which does call itself then it works fine, have a look code.
<script>
//window.obj2(); // problem
(function (window) {
window.obj2 = function(){
console.log('obj2 in window.object',this);
}
var parent = {
obj : function(){
//console.log(this);
obj2();
this.obj2();
window.obj2();
},
obj2 :function(){
console.log('obj2 in parent',this);
}
}
parent.obj();
}(window));
</script>
<body>
</body>
Related
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.
Hey guys am a bit confused in running a function from the other. What I have tried is:
var a = (function() {
var babe = function() {
console.log('yay');
};
})();
When I run the code like a.babe() it gives me error like TypeError: Cannot read property 'babe' of undefined. Why is it happening like this?
I want to call the function babe from a ... How can i do it?
I hope you guys can help me ...
Thanks in advance.
You are creating a function called babe and it stays only within the scope of the immediately invoked function expression (IIFE) surrounding it. And since you are not returning anything to the caller, by default, the function call will be evaluated to undefined and that will be stored in a. That is why you are getting the error,
TypeError: Cannot read property 'babe' of undefined
It means that, you are trying to access a property called babe on an undefined value. In this case, a is undefined.
Instead of all this, you can simply return the babe function from the IIFE, wrapped in an object, like this
var a = (function() {
return {
babe: function() {
console.log('yay');
}
};
})()
Now, that the returned object is assigned to a, you can invoke babe function like this
a.babe();
babe is a local variable to the IIFE in that code. It isn't returned. It isn't a property of anything. It isn't accessible.
You have to expose it publicly if you want it to call it from outside that function.
var a = (function() {
var babe = function() {
console.log('yay');
}
return babe;
})();
a();
var a = (function() {
var babe = function() {
console.log('yay');
}
return {
"babe": babe
};
})();
a.babe();
Why have you made a a self executing function? What you want to do is to make a function babe part of an Object a for that, simply do this:
var a = {
babe: function() {document.write('yay');}
}
a.babe();
I have made an object a and added a function babe inside it.. then used the dot notation to access the function inside object a
To use your code you must do
var a = (function() {
var babe = function() { console.log('yay'); }
return babe
})();
a();
To make it a.babe() look at #thefourtheye or #Quentin.
The dot syntax is used to access a "property" of an object. So, in a simple example, you could use something like:
var a = {
babe: function(){ console.log('yay') }
};
a.babe(); // yay
In the case of your example, if you want to create a closure to hide other variables and functions from the global scope, you have to return an object that will then get assigned to a:
var a = (function() {
return {
babe: function(){ console.log('yay') }
}
})();
a.babe(); // yay
Just remember, anytime you use a dot, the variable in front HAS to be an object.
Is javascript code read from the top down?
In other words if I have:
function Color(){
}
function Weather() {
}
If I wanted to incorporate some type of weather object inside the Color function would it be possible since Weather is defined afterwards?
The function Color won't know about Weather as it's being parsed, but it will once it is called. For example:
// Since variable declarations are hoisted to the top,
// myVar will be undefined (same as simply saying "var myVar;")
console.log(myVar); // <-- undefined
var myVar = 5;
console.log(myVar); // <-- 5
// test2 hasn't been defined yet, but it doesn't matter
// because test isn't being executed
var test = function() {
test2();
}
// This will throw an error: undefined is not a function
// because test2 isn't defined
test();
var test2 = function() {
alert("test2");
}
// This won't throw an error
test();
Essentially, you should execute after all functions have been defined. However, if you use the function functName() {} syntax, then it is hoisted just like a var statement.
function test() {
test2();
}
// Works!
test();
function test2() { alert("test2"); }
JavaScript is parsed "top-down" and Function Declarations are hoisted constructs - see var functionName = function() {} vs function functionName() {}. Parsing happens before the JavaScript execution itself starts; the following thus covers the evaluation semantics1.
Given the effect of function hoisting, the following code is valid, although it seems like it might not be:
function a(){
return b();
}
alert(a()); // alerts "b", even though "b comes later"
// This declaration IS hoisted
function b() {
return "b";
}
However, considering that even when using "var fn = .." (when the assignment is not hoisted) the ordering usually doesn't matter because the evaluation of the assignments happens before the usage:
var a = function () {
return b();
}
// alert(a()); <- this would fail, because b is not assigned yet
// This assignment is NOT hoisted
var b = function () {
return "b";
}
// But b is assigned before here, meaning that the order of the constructor
// functions still Just Doesn't Matter.
alert(a());
As such, in the case where there are two constructor functions (e.g. Color and Weather) which are [mutually] dependent, it doesn't matter where they are located in the same scope relative to each other.
1The thing that matters is the expression representing the dependency is resolvable when evaluated (which is relative to the evaluation code, but not related to the parsing/placement order of the functions).
so basically yeah you can implement something to a function that appears in a previous code.
hole this helps you understand it better.
var weather = function() {
if (weather === red) {
console.log("weather is represented by the color red");
}
else {
console.log("Not the right color");
}
};
weather(red);
I have tried folllowing two ways of referring a function:
First
let a = function() {
somefunction();
}
Second
let a = somefunction;
Where somefunction is the following in both cases:
function somefunction() {
alert("hello");
}
Is there any difference between these two ways?
Yes, there is a difference between your two examples.
In the first case, you are defining a new anonymous (unnamed) function which calls somefunction. You are then assigning your new function definition to the variable a. a holds a reference to your new function.
In the second case, you are simply assigning your original function of somefunction to the variable a. The variable a then holds a reference to somefunction. You are not creating a new function as you are in the first case.
I think this example may make the difference clear. arguments is an array like object that contains each of the arguments passed to a function.
Try running each of these lines on your favorite browser console.
var somefunction = function() { console.log(arguments); };
Your first example demonstrates defining a named function a that closes around the named function somefunction.
var a = function() { somefunction(); };
Your second example makes a reference, b, directly to somefunction. This makes invoking b the same as invoking somefunction.
var b = somefunction;
Now if you call each of these a and b with some arguments you will see the difference.
=> a('a', 1);
[]
=> b('a', 1);
['a', 1]
In the first case the arguments object is empty. That's because the arguments that were passed to a were not forwarded onto somefunction.
In the second case the arguments are available to somefunction, because some function is being called directly.
Here is how you could redefine a so that it were functionally equivalent using apply
var a = function() { somefunction.apply(this, arguments); }
Running this at your console prints the argument array.
=> a('a', 1);
['a', 1]
var a = function(){
somefunction();
}
Is an Anonymous Function attributed to a variable.
somefunction :function() {
alert("hello");
}
Is an declaration of a function throungh the Object Literal notation.
The diference are shown when you are creating an object. The anonymous function are not acessible as a "public" method, instead in the Object Literal notation, that are acessible from outside.
As Douglas Crockford said, in JS the Good Parts, the first declaration are just a function and the second one could be a method.
In the first case, you are creating a function which calls someFunction(), then you assign that function to a, so now calling a() calls an anonymous function which in turn calls someFunction().
In the second case, a and someFunction become the exact same thing, calling a() is the same as calling someFunction().
The way you're setting var a by accessing the function is clearly out of scope.
So I suspect you have a typo : instead of = :
var somefunction = function() {
alert("hello");
};
somefunction(); // hello
...Now that your first and second makes sense with the code above:
Anonymous Function stored in variable:
var a = function(){
alert('Hey');
somefunction();
};
a(); // Hey // hello
Variable as Function Reference
var a = somefunction;
a(); // hello
In the other case than:
var objLiteral = {
somefunction : function() {
alert("hello");
}
};
var a = objLiteral.somefunction;
a(); // hello
How do I explain the role of the arguments passed in the beginning vs end of a wrapped Javascript closure as the one shown below?
(function($, window) {
return $(function() {
return alert("js!");
});
})($, window);
The first appearance are function parameters, the second is passing values for those parameters when executing the function.
Keep in mind, the parameters to the function don't need to match the names being passed (this could, in fact, cause confusion later on):
(function(jQuery, w) {
return jQuery(function(){
return alert("js!");
});
})($, window);
Would work the same way.
In that way you are passing arguments that will be safe in the scope from an overwrite in the future. For example:
var a = 1
(function(a){
setTimeout(function(){
console.log('This variable is still safe', a);
},2000)
})(a)
a = 0
console.log('has changed', a)
So in your example you can be sure that $ and window will be that what you are expecting.
It may be easier to explain if you change the argument names and name the function
(function init($, win) {
return $(function() {
return alert("js!");
});
})(jQuery, window);
The init function is being passed the parameters jQuery and window immediately as it's defined, they are available as arguments to the init function as $ and win
If you break it out into the equivalent code, that may also be easier to understand
function init($, win) {
return $(function() {
return alert("js!");
});
}
init(jQuery, window);
The set of parameters on top is where the parameters are recieved, and the set of parameters on the bottom is where they are passed.
They're ensuring that their closed copies of the global variables don't get reassigned outside of the closure. It is a way of protecting your code against other (potentially poorly written) code. Consider this example:
var $ = 'foo';
var blah = (function($) {
return function () {
alert($);
};
})($);
var shizzam = (function() {
return function () {
alert($);
};
})();
// someone evil overwrites my $ var
$ = 'bar';
// blah still works
blah();
// but shizzam is now borked
shizzam();
http://jsfiddle.net/xfTcq/
When a function returns another function it can be enclosed on parentesis to be immediate executed.
The last parenthesis are the passed arguments to it.
You can do some tests do understand:
var a (function(){});
typeof a;
a.toSource()
typeof (function(){});
(function(){}).toSource()