When looking at the code for the addSuffix function
const addSuffix = (x) => {
const concat = (y) => {
return y + x
}
return concat;
}
let add_ful = addSuffix("ful");
If I were to console.log(add_ful); why do I get
(y) => {
return y + x
}
instead of
(y) => {
return y + "ful"
}
?
This is the most confusing point about closures for me, I understand that I can return a function, but I'm not sure where the reference to "ful" is being stored in the function.
Where is the value of x being stored in the add_ful function?
The value is not stored in the code. It does not get inlined at every place where x is used in the closure - the code still contains a variable x that is dynamically resolved when encountered (it's also still writable).
The value is stored in the scope object containing the variable, and this is referenced by the function object (that's what we call a closure). You can also inspect this hidden [[Scope]] slot in the devtools when you are logging the function object (and not just the function code produced by .toString()):
console.log logs a string representation of the function itself. It doesn't enquire into the state of the function and display the current values that are being referenced. It's just showing the syntax you used to create the function.
However, if you set a breakpoint and walk through the execution, you can see the state of the variables in scope using your debugging tools.
Related
var x = 5;
function f0() {
return function () {
var y = 10;
var z = x + y;
console.log('x + y is: ' + z);
}
}
var myFunc = f0();
myFunc();
x = 10;
myFunc();
In the example above, I expected x + y is: 15 to be printed in the second time as well. Because, to the best of my knowledge, what is returned from f0 is a closure. I thought that a closure takes a snapshot of the variables at its environment at the time it is defined. Hence, I thought that changing x with x = 10; wouldn't affect the free variables used in a closure.
But apparently I was wrong. Could you tell me why does changing x change the result of the function which is returned from f0?
Is it because what is returned from f0 is not a closure?
Is it because a closure does not record the values of the variables at the scope it is being returned to?
Is it because of another reason?
Is it because what is returned from f0 is not a closure?
No. Every function is a closure in JavaScript.
Is it because a closure does not record the values of the variables at the scope it is being returned to?
Yes. A closure does not record the values, taking a snapshot of the current state. It simply does record the reference to the scope. And it's the scope it was defined in, not the scope it is returned to.
I am going to digress a little bit in the beginning to get concept of closures clear.
In a language like c++, it is considered a bad idea for a function to return local variables, unless they are allocated on heap.
example:
x foo() {
x obj;
return obj;
}
cout<< foo() << endl;
In above example, obj would be destroyed as soon as we return from foo, and hence, we end up getting garbage as output.
In Javascript, that would be legal, due to the concept of closures.
A closure is a special kind of object that combines two things: a
function, and the environment in which that function was created. The
environment consists of any local variables that were in-scope at the
time that the closure was created.
So, in your case, one variable(y) would be from environment of enclosing function, but x is a global variable, and can be changed from outside function.
The inner enclosing variables(such as y) are also called private variables, since the only way to get to them would be through myFunc() in your case.
This question may be answered elsewhere but I wasn't even sure how to begin searching for the answer. I'm new to JavaScript so this one is a struggle for me to understand.
Given the following code:
function multiple(n) {
function f(x) {
return x * n;
}
return f;
}
var triple = multiple(3);
var quadruple = multiple(4);
When I pass the following into the console:
console.log(triple(5));
I get what I expect, that is, 15. Likewise with any number, it will be tripled (or quadrupled if I used the second function).
But when I type triple into the console I get the following code:
f(x) {
return x * n;
}
Shouldn't the console return...
f(x) {
return x * 3;
}
...since 3 is coded into the function by virtue of the following code:
var triple = multiple(3);
3 is not hard-coded into the function. The code of f refers to the variable n, not the number 3. In your code, it so happens that there is no way to modify n, but imagine some code where there is a way to modify n:
function multiple(n) {
function f(x) {
return x * n;
}
function modifyN(newN) {
n = newN;
}
return { f: f, modifyN: modifyN };
}
var resultFor3 = multiple(3);
var triple = resultFor3.f;
var modifyTripleN = resultFor3.modifyN;
As you can see n is not hard-coded; it's no different from any other variable. In your specific example there is no way to modify n after the termination of multiple, but that does not make the values inside of the closure created by the invocation of multiple in any way "hard-coded".
Typing triple simply shows the source code of your function.
since 3 is coded into the function by virtue of the following code
That is an incorrect statement. You're not changing the source code of the function. To change the source code, you would have to redefine the entire function. All you're doing is passing in a parameter. The console is giving you the correct output.
When you're passing in a parameter to a function, on a high-level, at runtime it's just looking for whatever value is stored at the memory address for that variable (or something like that). But it is not rewriting the source code of the function.
Well, it is the same as it would if you had:
var n = 3;
function f(x) {
return n * x;
}
If you log f you will see the function above, but when you call it n will get its value from the closest variable called n in the scope chain, in our case n = 3, the value for the n declared in the global scope.
I don't know the exact way in which the JS engine stores the n variable inside that closure (in your case the closure created by the multiple function), but what is the important thing is that variables inside a closure are saved by reference not by value.
I wrote code like the following:
function setAtoB(a, b) {
console.log('entered function');
a = b;
}
var x = {};
var y = {'t':3};
setAtoB(x, y);
console.log(x);
I then got output like this:
entered function
{}
It seems to me that x should have been {'t':3}. Does anyone know why it's still {}, and how I can assign values within a function?
In the setAtoB function, you're replacing a with b, which breaks a's reference to the caller one level higher in the call stack. When passing in objects into functions, you can replace their properties without breaking that link, but the moment you perform any type of reassignment, that link breaks and a new object is created.
For example, if you instead replace just the properties, then the references are preserved:
function setAtoB(a, b) {
console.log('entered function');
a.t = b.t;
}
var x = {};
var y = {'t':3};
setAtoB(x, y);
console.log(x); // output: Object {t: 3}
JavaScript is always pass-by-value, so you just can't directly do what you describe. You can modify the properties of an object when a reference to it is passed into your function, but you cannot change the original variable used in the calling environment. In other words, in the call:
setAtoB(x, y);
it's a copy of the value of variable "x" that's passed to the function. The value of variable "x" is a reference to an object, so a copy of that reference is what's passed. That reference works just as well as the copy still present in "x" to make changes to the referenced object, but changing the parameter that contains the copy has no effect on the value of "x".
This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 8 years ago.
While reading a different topic I came across this piece of code:
function loadme() {
var arr = ["a", "b", "c"];
var fs = [];
for (var i in arr) {
var x = arr[i];
var f = function() { console.log(x) };
f();
fs.push(f);
}
for (var j in fs) {
fs[j]();
}
}
This will output: a,b,c,c,c,c. The problem here as explained by the author is that the x var is hoisted at the start of the function and therefore does not keeps it's value when it is used in the loop. What I do not understand is why is c assigned to x on the second console.log for 3 times? Can someone explain?
This situation is, in fact, quite easy to explain and it occurs in many programming languages, not just JavaScript.
Let's first take the output sequense a,b,c,c,c,c and discard the first three elements - a,b,c because this is what gets printed when you execute your function f() inside the first for loop.
So, we're left with the sequense c,c,c which gets printed when we iterate over the fs array. The reason why you don't get a,b,c printed is because the x parameter that you have inside your first for loop is captured by reference (not sure if the definition is valid, though) by your f() closure (remember, every function in JavaScript is a closure of some sort).
Now, since the console.log(x) expression is evaluated when you call the f(), the current value of the captured x parameter will be passed as an argument. While the code works, as seems to be expected, when you invoke f() inside the first for loop, the x is what has just been assigned from arr[i] so you get a,b,c. But when you exit the loop, the x (even though it's unavailable to the outer scope) is still captured by f() but after the first loop it has a value c (the one that it got on the last iteration) and that is what gets evaluated when you iterated over your functions the second time.
This is, in fact, can be a source of many confusing bugs and so some languages can detect this and notify the developer (for example, C# compiler, when it sees constructs like this, produces the following warning: Access to modified closure).
To fix the problem, you just need to capture the current value of x inside your first for loop:
for (var i in arr) {
var x = arr[i];
var f = (function(x) {
return function() { console.log(x) };
})(x);
f();
fs.push(f);
}
Here we use IIFE (Immediately-Invoked Function Expression) to capture the current value of x.
Hope this helps.
var x = arr[i];
var f = function() { console.log(x) };
In these two lines, console.log(x) thinks that it just has to print x. So, all the three functions are created that way only. So, when you immediately execute the functions, the value of x is different in each of the iterations. But when the looping is over, the variable x retains the last value it held and when the dynamically created functions are executed, they simply print the value of x which is c.
So, in order to fix this, you have to have your own copy of x, for each dynamically created function. Normally, we retain the current state of the variable which changes in the loop, with a function parameter, like this
var f = function(x) { return function() { console.log(x) } }(x);
Now, we are creating a function and executing it immediately, which returns another function and that returned function actually prints the value of x.
function(x) {
return function() {
console.log(x)
}
}(x);
We are passing the value of x as a parameter to the wrapper function and now the current value of x is retained.
I'm trying to wrap my head around closures in Javascript.
Here is an example from a tutorial:
function greeter(name, age) {
var message = name + ", who is " + age + " years old, says hi!";
return function greet() {
console.log(message);
};
}
// Generate the closure
var bobGreeter = greeter("Bob", 47);
// Use the closure
bobGreeter();
The author said that this is an effective way of using closure to make private variables, but I don't get the point.
Could someone enlighten the benefits of coding like this?
A closure is a pair of a function and the environment in which it was defined (assuming lexical scoping, which JavaScript uses). Thus, a closure's function can access variables in its environment; if no other function has access to that environment, then all of the variables in it are effectively private and only accessible through the closure's function.
The example you provided demonstrates this reasonably well. I've added inline comments to explain the environments.
// Outside, we begin in the global environment.
function greeter(name, age) {
// When greeter is *invoked* and we're running the code here, a new
// environment is created. Within this environment, the function's arguments
// are bound to the variables `name' and `age'.
// Within this environment, another new variable called `message' is created.
var message = name + ", who is " + age + " years old, says hi!";
// Within the same environment (the one we're currently executing in), a
// function is defined, which creates a new closure that references this
// environment. Thus, this function can access the variables `message', `name',
// and `age' within this environment, as well as all variables within any
// parent environments (which is just the global environment in this example).
return function greet() { console.log(message); };
}
When var bobGreeter = greeter("Bob", 47); is run, a new closure is created; that is, you've now got a new function instance along with the environment in which it was created. Therefore, your new function has a reference to the `message' variable within said environment, although no one else does.
Extra reading: SICP Ch 3.2. Although it focuses on Scheme, the ideas are the same. If you understand this chapter well, you'll have a good foundation of how environments and lexical scoping work.
Mozilla also has a page dedicated to explaining closures.
The purpose of a closure is so that the variables you use inside a given function are guaranteed to be "closed" which means they do not depend on external variables - they only depend on and use their arguments. This makes your Javascript methods closer to a pure function, that is, one that returns the same value for the same given arguments.
Without using closures, your functions will be like Swiss cheese, they will have holes in them. A closure plugs up those holes so the method doesn't depend on variables higher in the scope chain.
Now, up until this point, my answer has been simply about organizing your code and style. So take this simple example. At the line with the comment, I invoke a function and the value of the variable a is captured for future use.
var a = "before";
var f = function(value) {
return function()
{
alert(value);
}
} (a); //here I am creating a closure, which makes my inner function no longer depend on this global variable
a = "after";
f(); //prints "before"
Now, why would you need to do this? Well, here's a practical example. Consider the following code that uses jQuery to add 5 links to the document. When you click a link, you would expect it to alert the number associated with the link, so clicking the first you would think would alert 0, and so on. But, this is not the case, each link will alert the value of 5. This is because the function I define depends on the variable i which is being modified outside the context of the function. The function I pass into bind is a Swiss cheese function.
for (var i = 0; i < 5; i++)
{
var a = $('<a>test link</a>').bind('click', function(){
alert(i);
});
$(a).appendTo('body');
}
Now, let's fix this by creating a closure so each link will alert its correct number.
for (var i = 0; i < 5; i++)
{
var fn = function (value) {
return function() {
alert(value);
};
} (i); //boom, closure
var a = $('<a>test link</a>').bind('click', fn);
$(a).appendTo('body');
}
I don't think this is a good example for private variables, because there are no real variables. The closure part is that the function greet can see message (which is not visible to the outside, hence private), but it (or anyone else) is not changing it, so it is more of a constant.
How about the following example instead?
function make_counter(){
var i =0;
return function(){
return ++i;
}
}
var a = make_counter();
console.log(a()); // 1
console.log(a()); // 2
var b = make_counter();
console.log(b()); // 1
console.log(a()); // 3
A better example may be
function add(start, increment) {
return function() {
return start += increment;
}
}
var add1 = add(10, 1);
alert(add1()); // 11
alert(add1()); // 12
Here, every time you call the returned function, you add 1. The internals are encapsulated.
The returned function still has access to its parents variables (in this case, start and increment).
On a lower level of thinking, I think it means that the function's stack is not destroyed when it returns.
Once you "get it" you will wonder why it took you so long to understand it. That's the way way I felt anyways.
I think function scope in Javascript can be expressed fairly concisely.
The function body will have access to any variables that were visible in the lexical environment of the function declaration, and also any variables created via the function's invocation -- that is, any variables declared locally, passed through as arguments or otherwise provided by the language (such as this or arguments).
It's called "closures" because they are "closed" around free variables, and there are much more ways to use it then only hiding state. For example, in functional programming, where closures came from, they are often used to reduce parameters number or set some constant for a function. Let's say you need function goodEnough() that will test if some result is better then some threshold. You can use function of 2 variables - result and threshold. But you can also "enclose" your constant inside function:
function makeThresholdFunction(threshold) {
return function(param) {
return (param > threshold);
}
}
var goodEnough = makeThresholdFunction(0.5);
...
if (goodEnough(calculatedPrecision)) {
...
}
With closures you can also use all the tricks with functions such as their composition:
function compose(f1, f2) {
return function(arg) {
return f1(f2(arg));
}
}
var squareIncremented = compose(square, inc);
squareIncremented(5); // 36
More on closure design and usage can be found at SICP.
I found this a pretty helpful article.
When is a function not a function?
//Lets start with a basic Javascript snippet
function generateCash() {
var denomination = [];
for (var i = 10; i < 40; i += 10) {
denomination.push(i);
}
return denomination;
}
This a basic function statement in Javascript that returns an array of [10,20,30]
//--Lets go a step further
function generateCash() {
var denomination = [];
for (var i = 10; i < 40; i += 10) {
denomination.push(console.log(i));
}
return denomination;
}
This will print 10, 20 ,30 sequentialy as the loop iterates, but will return an array of [undefined, undefined, undefined], the major reason being we are not pushing the actual value of i, we are just printing it out, hence on every iteration the javascript engine will set it to undefined.
//--Lets dive into closures
function generateCash() {
var denomination = [];
for (var i = 10; i < 40; i += 10) {
denomination.push(function() {
console.log(i)
});
}
return denomination;
}
var dn = generateCash();
console.log(dn[0]());
console.log(dn[1]());
console.log(dn[2]());
This is a little tricky, what do you expect the output will be, will it be [10,20,30]? The answers is no, Lets see how this happens. First a Global execution context is created when we create dn, also we have the generatecash() function. Now we see that as the for loop iterates, it creates three anonymous function objects, it might be tempting to think that the console.log within the push function is getting fired too, but in reality it is not. We haved invoked generateCash(), so the push function is just creating three anonymous function objects, it does not trigger the function. At the end of the iteration, the current local context is popped from the execution stack and it leaves the state of i : 40 and arr:[functionobj0(), functionob1(), functionobj2()].
So when we start executing the last three statements, all of them output 40, since it is not able to get the value of i from the current scope, it goes up the scope chain and finds that the value of i has been set to 40. The reason all of them will fire 40 is beacause every single component of dn lies in the same execution context and all of them on being not able to find the value of i in their current scope will go up the scope chain and find i set as 40 and output it respectively