Javascript module pattern and function invocation - javascript

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();

The first example shows two invocations of f1().
The first invocation of f1() creates a new variable scope with x set to 1, and returns the object with the methods. The .add() then sets that x to 5.
The second invocation of f1() creates another new variable scope with x again set to 1, and returns the object with the methods. The .result() then returns that x which is still 1.
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.

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();

Related

Can you explain the order of execution in the code mentioned below?

function makeMultiplier (multiplier){
var myFunc = function (x){
return multiplier * x;
}
return myFunc;
}
var multiplyBy3 = makeMultiplier(3);
console.log(makeMultiplier(3)(10));
Here, I don't understand why and how does the var multiplyBy3 variable acts as a reference to the myFunc function mentioned above
The return value of executing the function makeMultiplier is function myFunc. This is being assigned to variable multiplyBy3 . Hence it will act as a reference to myFunc function
Order of execution:
makeMultiplier is defined
makeMultiplier is called with arg 3 and returns a new function and that returned function is stored in a variable named multiplyBy3.
console log called with makeMultiplier is called with 3, returns a new function and it is called with argument 10
In JavaScript all the non primitive objects' assignments are stored as reference, but not as value. Example variable assignments, argument passing to functions where it basically assigned to the parameter which is a local variable inside the function.
However, second call to the multiplier with arg 3 is a different function, the references are different.
Also you can test those with Object.is() static method.
In your code, you don't actually use multiplyBy3, but here's your code modified to use it as the reference to the inner myFunc(3):
function makeMultiplier(multiplier) {
var myFunc = function(x) {
return multiplier * x;
}
return myFunc;
}
var multiplyBy3 = makeMultiplier(3);
console.log(multiplyBy3(10));
When setting the multiplyBy3 variable, we call the makeMultiplier function with 3 as our multiplier argument. This returns a reference to function(x) { return 3 * x; } which is assigned to multiplyBy3.
Calling multiplyBy3(10) then results in the value of 30 due to multiplying 3 by the argument of 10. This is equivalent to your original code makeMultiplier(3)(10)
In the following code snippet, I modified your code to use multiplyBy3 and threw in some console.log statements to show the steps taken both outside and inside the functions.
function makeMultiplier(multiplier) {
console.log("[enter] makeMultiplier");
var myFunc = function(x) {
console.log("[enter] myFunc");
return multiplier * x;
}
return myFunc;
}
console.log("[before] 'var multiplyBy3 = makeMultiplier(3);'");
var multiplyBy3 = makeMultiplier(3);
console.log("[after] 'var multiplyBy3 = makeMultiplier(3);'");
console.log("[before] 'console.log(multiplyBy3(10));'");
console.log(multiplyBy3(10));
console.log("[after] 'console.log(multiplyBy3(10));'");
Additionally, I'll show an alternate example where we multiply by 4:
function makeMultiplier(multiplier) {
console.log("[enter] makeMultiplier");
var myFunc = function(x) {
console.log("[enter] myFunc");
return multiplier * x;
}
return myFunc;
}
console.log("[before] 'var multiplyBy4 = makeMultiplier(4);'");
var multiplyBy4 = makeMultiplier(4);
console.log("[after] 'var multiplyBy4 = makeMultiplier(4);'");
console.log("[before] 'console.log(multiplyBy4(10));'");
console.log(multiplyBy4(10));
console.log("[after] 'console.log(multiplyBy4(10));'");

Closure, where is the value getting stored?

Over here, I am returning a function which is closed over the 'i' variable, creating a closure.
var myFunc = function(){
var i = 0;
function increment(){
return ++i;
console.log(i);
}
return increment
}
now If I assign this function to other variables like
var newFunc = myFunc();
var newFunc2 = myFunc();
calling any of them will result in
newFunc() // 1
newFunc() // 2
newFunc() // 3
newFunc2() // 1 ??
Where is the value of var i getting stored?
is it getting stored in the execution context of each function so that it can be changed only when we call that specific function.
I saw you define the variable i inside the
myFunc
which means that the scope of the variable i will be within that function. So whenever you call this function, it will create create its own i.

Access local variable inside a callback function

var inner = function() { console.log(x); }
// test 1
(function(cb) { var x = 123; cb(); })(inner);
// test 2
(function(cb) { var x = 123; cb.apply(this); })(inner);
// test 3
(function(cb) { var x = 123; cb.bind(this)(); })(inner);
// test 4
(function(cb) { cb.bind({x: 123})(); })(inner);
All tests result in:
ReferenceError: x is not defined
Do someone know how it is possible to access 'x' as a local variable inside the callback?
Fact: when you do var inner = function() { console.log(x); } in your first line, x is not defined. Why? Because, inside your inner function, there's no local declaration of x (which would be done with var x = something). The runtime will then look up in the next scope, that is the global scope. There isn't, also, a declaration of x, so x is also not defined there.
The only places where there is a variable called x are inside each one of your 4 IIFEs following. But inside the IIFEs, each x is a different variable, in a different scope. So, if what you want is to console.log() the x defined inside each IIFE, you are taking the wrong approach.
Keep in mind that, when you define inner, you are capturing the environment inside the function's closure. It means that, whatever value could x have there (in the declaration of the function), would be the available value to the x variable later, when the inner function would be used. The fact that your x there is not defined is only an accessory, and is not what is causing the undesired behavior.
So, what happens is that when you call your inner function inside any of your IIFEs, the x referred to inside the inner function declaration is a captured value of what x had as a value when the function was defined, not the value that x has now in the scope where the function is currently being called. This is what is called lexical scope.
To solve this, you would have to pass the value that you want to console.log() inside the inner function as a parameter to the inner function, as so:
var inner = function(x) { console.log(x); }
// test 1
(function(cb) { var x = 123; cb(x); })(inner);
The only way to access the local variable x in the callback, is to pass it as an argument:
var inner = function(some_var) { console.log(some_var); }; //logs 123
(function(cb) { var x = 123; cb(x); })(inner);
OR
var inner = function(some_var) { console.log(some_var); }; //logs 123
(function(cb) { var x = 123; cb.apply(this,[x]); })(inner);
OR
var inner = function(some_var) { console.log(some_var); }; //logs 123
(function(cb) { var x = 123; cb.call(this,x); })(inner);
FURTHER
Because JS is lexically scoped, trying to reference the local variable after the anonymous function has finished executing is impossible by any other means. If you don't pass it as an argument to make it available elsewhere, JS will see it as non-reachable and it will be eligible for garbage collection.
You could redefine the callback function in the current scope:
var inner = function() { console.log(x); }
(function(cb) { var x = 123; eval('cb = ' + cb.toString()); cb(); })(inner);
// or
(function(cb) { var x = 123; eval('(' + cb.toString() + ')')(); })(inner);
This will not work if the function relies on anything in the scope in which it was originally defined or if the Javascript file has been minified. The use of eval may introduce security, performance, and code quality issues.
Have you tried using events? Emit an event inside the anonymous function, then subscribe to it in your own function somewhere else that carries out your logic.

Assign a function with custom parameters without calling the funcion

I've a function A which accepts at run-time another function B as parameter and calls it. The problem is the function B needs some parameters, but I don't know how to pass the function B, with parameters, to the the function A.
Example:
function callerFunction(c)
{
alert("The caller is calling the function!");
c(c.arguments);
};
var a = "hello";
function thisOne(d)
{
d = "I changed my way";
alert(d);
};
callerFunction( /* I NEED TO PASS THE 'thisOne' with the parameter/variable 'a' here, and then call it inside 'callerFunction' */);
Just pass a closure:
callerFunction(function() { thisOne(a); });
And call it as c(), not c(c.arguments).
Note that this anonymous function will reference the a variable, not the value a had at that moment. So if callerFunction() was to store this function object and call it later, if you changed the value in a between passing the anonymous function and the time it is called, the value of a from the perspective of the anonymous function would have changed:
var a = 1;
var fn = function() { console.log(a); };
fn(); // Logs 1
a = 2;
fn(); // Logs 2

Minimum viable JavaScript closure

The top answer on Stack Overflow regarding JavaScript closures defines them as (paraphrase):
A function that simply accesses variables outside of your immediate lexical scope that are not deallocated after the function returns.
Based strictly on this definition it seems like we can reduce the minimum viable closure (that does something useful) to a function containing no local variables that alters something in the global scope:
var x = 0;
function foo() {
x = x + 1;
return x;
}
foo(); // returns 1
foo(); // returns 2, et cetera
However, usual examples contain nested functions and variables that are "enclosed". Is this example a closure (or perhaps the global scope is now the closure)? Or is the definition incomplete?
Thanks!
No, because you simply don't use a closure here, there's only one scope, the global one, you're just using a global variable.
The definition you cite is ambiguous there :
after the function returns
In this definition, the "function" which "returns" is the one whose scope holds the variable, that is the external one. As there's no outer function, and the global scope never ends, there's no closure.
A closure would be like this :
var foo = (function(){
var x = 0;
return function() {
x = x + 1;
return x;
}
})(); // the function returns but x keeps being usable by the inner function
foo(); // returns 1
foo(); // returns 2, et cetera
And a less useless closure would be like this :
function makeFoo(){
var x = 0;
return function() {
x = x + 1;
return x;
}
}
var foo1 = makeFoo(), foo2 = makeFoo();
foo1(); // returns 1
foo2(); // returns 1
foo1(); // returns 2, et cetera
Yes, it is a closure. In the top answer, it actually provides a simplest closure example:
var a = 10;
function test() {
console.log(a); // will output 10
console.log(b); // will output 6
}
var b = 6;
test();
This is basically identical to your example, the scope of the function definition just happens to be the same as the parent of execution context.
When a Javascript function is invoked, a new execution context is created. Together with the function arguments and the parent object, this execution context also receives all the variables declared outside of it (in the above example, both 'a' and 'b').
You can actually use a new scope to replace the global scope in your example:
(function(){
var x = 0;
function foo(){
x = x + 1;
console.log(x);
}
foo(); // output 1
foo(); // output 2
})();

Categories