Hello I have started to learn some javascript and I can't wrap my head around this in "normal" functions. I don't understand why the following two functions output different results. f2 outputs 5, while f1 outputs 1. Why is that?
var f1 = function(){
var x= 1;
var add = function(){
x=5;
};
var result = function(){
console.log(x);
};
return {
add: add,
result: result
};
};
f1().add();
f1().result();
var f2= (function(){
var x= 1;
var add = function(){
x=5;
};
var result = function(){
console.log(x);
};
return {
add: add,
result: result
};
})();
f2.add();
f2.result();
2 Answers 2
The first example shows two invocations of f1().
The first invocation of
f1()creates a new variable scope withxset to1, and returns the object with the methods. The.add()then sets thatxto5.The second invocation of
f1()creates another new variable scope withxagain set to1, and returns the object with the methods. The.result()then returns thatxwhich is still1.
The second example only invokes f2() once, so there's no new variable scope with x and new methods being created.
So basically f1's two invocations initializes x with each call, and returns two different objects with methods that closer over the two different x variables.
The f2 is invoked once so there's one x variable shared by the one object with methods returned. Therefore the .add() call and the .result() call are using the same x variable.
8 Comments
f1 creates a new execution context with a new x each time, whereas f2 is called once and the same execution context is on the scope chain of add and result so they share the same x.f2.Let me outline what happens in your code:
// Declares a function named f1.
var f1 = function () {
// Searches each scope (the scope of f1, the scope containing f1, etc.) for
// a variable named x. If found, it will reassign it to 1. If the search reaches
// the global scope and no variable is found it will declare and initialize
// a global variable.
x = 1;
// Declares a local variable named add to a function that reassigns the value of x.
var add = function () {
x = 5;
};
// Declares a local variable named result to a function that logs the value of x.
var result = function () {
console.log(x);
};
// Returns an object containing each function.
return {
add: add,
result: result
};
};
// Calls f1 and the returned add function.
f1().add();
// Calls f1 again (which reassigns x) and calls the returned result function.
f1().result();
// Creates a variable named f2 and assigns to the result of applying an anonymous
// function. f2 now references the returned object.
var f2 = (function () {
// Reassigns x, does not create a new variable.
x = 1;
var add = function () {
x = 5;
};
var result = function () {
console.log(x);
};
return {
add: add,
result: result
};
})();
// The difference now is that the function that contains add and result is only
// called once, during the initialization of f2. Had you written var g = f1();
// g.add(); g.result(); you would have gotten the exact same results.
f2.add();
f2.result();
xglobal variable, as you didn't declare it withvar, is that the intention?