So I'm new to programming and I'm trying to learn JS with the book Eloquent Javascript.
So far so good, until I reached an example with the following code
function makeAddFunction(amount) {
function add(number) {
return number + amount;
}
return add;
}
var addTwo = makeAddFunction(2);
var addFive = makeAddFunction(5);
show(addTwo(1) + addFive(1));
note: show is like alert, only it shows the variables on the screen of a JS console the tutorial has integrated.
The author says this is an example to show how lexical scoping allows to synthesise functions.
Chapter here
What I don't understand is how addTwo and addFive, which supposedly are variables, can send parameters to the functions makeAddFunction and add, and more specifically, how does the function add knows that the parameter the variables are sending is the parameter number.
Thanks for your help guys!
In javascript, a function is a first-class object, that is, it can be passed around, assigned to a variable, etc. The variables addTwo and addFive contain functions. Those functions are generated by the "factory" function makeAddFunction.
The functions that addTwo and addFive contain carry with them the scope that existed when they were created. That is, when addTwo, for example, was created, the parameter "amount" was 2. So addTwo, in essence, is the following function:
function addTwo(number) {
return number + 2;
}
When someone calls addTwo(), it's not passing anything back to makeAddFunction. MakeAddFunction has already run and is finished. However, the scope created within makeAddFunction (in which "amount" equals 2) lingers in the addTwo function.
addTwo and addFive are variables -- but they're function variables. Look at typeof(addTwo) -- it's a function. It's like if you did this:
var addTwo = function(x) { return x + 2; };
It's the same as this:
function addTwo(x) { return x + 2; }
(Edit: As Šime pointed out, they aren't exactly the same. See here for an explanation of the difference between the two.)
The example will hopefully make sense once you understand that. You can even do weird things like this, declaring an anonymous function and invoking it right away:
var seven = function(x) { return x + 2; }(5);
Which is literally, at the physical machine code level, the exact same as: Which is equivalent to for all purposes relevant to this question:
function addTwo(x) { return x + 2; }
var seven = addTwo(5);
Edit:
Perhaps a less confusing "prequel" to this is the following:
function makeTheAddTwoFunction()
{
return function(x) { return x + 2; }
}
var addTwo = makeTheAddTwoFunction();
This is silly, but serves to illustrate functions that make functions. Of course, that sort of function usually will accept arguments so that it can make different functions each time, but there you go.
I think the key to understanding that example is understanding that functions can return other functions (just like any other variable). Documenting that code will go a long way in helping understand that concept.
/**
* Creates an adder function
* #param {number} amount Amount to add
* #return {function} Method that adds 'amount' to its argument.
* See the documentation of add for its signature
*/
function makeAddFunction(amount) {
/**
* Everytime makeAddFunction is called, a new instance of add is created
* (and returned) that holds on to its copy of 'amount' (through the closure)
* #param {number} number value to add to 'amount'
* #return {number} 'amount' + 'number'
*/
return function add(number) {
return number + amount;
};
}
// addTwo now is a reference to a function that when called
// adds 2 to whatever is passed in
var addTwo = makeAddFunction(2);
// addFive Adds 5 to its argument
var addFive = makeAddFunction(5);
// addTwo(1) = 3, addFive(1) = 6, therefore, output is 9
show(addTwo(1) + addFive(1));
Re: What I don't understand is how addTwo and addFive, which supposedly are variables, can send parameters to the functions makeAddFunction?
addTwo and addFive are variables. But their values are not simple scalars (numbers, strings, etc). Rather, their values are functions. Since their values are functions, it is fine to invoke those functions. Eg, addTwo(1)
Re: and more specifically, how does the function add knows that the parameter the variables are sending is the parameter number?
The function add is calling its first parameter number. So later, when you call the function via a variable, eg, addOne, the first parameter given to addOne becomes number.
ps If you're thinking to yourself, "Self, this is pretty tricky!" Then you're right--and that's the entire purpose of the example, to show something tricky. How often you'll use this technique may vary from never to every so often.
The best way to think of a piece of code like this is to substitute values and interpet in your mind
// when this one is invoked
var addTwo = makeAddFunction(2);
// makeAddFunction
// becomes something like
function makeAddFunction(2) {
function add(number) {
return number + 2;
}
// return a function, that adds
// 2 to every number it gets
return add;
}
// therefore this function call
// will add 2 to 1 and return 3
addTwo(1);
As always, here are the Jibbring notes on JavaScript Closures. It discusses scopes, execution contexts, variable/property resolution, etc...
While JavaScript closures are lexical, execution contexts (which may contain properties) are bound (think Python or Ruby) and not just "free variables" (as is the case with C# or Scala). This is the reason why new variables can only be introduced in new function scopes. (Modern Mozilla implementations introduce let).
Related
This is not a debugging question or a how-to question. This is a conceptual question.
I was finding it hard to wrap my head around what this "second scope" thing is, but overlooking the details I came up with this explanation:
If a function is stored (in some way) like this:
{
// function body written using undefined parameters.
// When the function is called the arguments are assigned to the parameters.
}
Declaring default parameters does this:
{ // Second scope
parameter1 = "something"
parameter2 = 5
{
// function body written using the above parameters.
// When the function is called the arguments or default values get assigned to the parameters.
}
}
Is this what really happens under the hood? If not, then what happens in there? The ECMAScript docs are way above my level. Maybe someone could provide the explanation in layman's terms? Thanks!
That's a pretty good explanation! Yes, the parameter list has its own scope. Let me expand on your explanation a bit and then explain why the additional scope there.
When you call a function without default parameter values, a new scope is created for the body of the function, and the parameters are created in that scope like top-level variables in the function. So, conceptually:
<<
let param1 = /*...the argument value provided for param 1 if any */;
let param2 = /*...the argument value provided for param 2 if any */;
// Start of function code
var variable1;
let variable2;
// End of function code
>>
(I'm using <</>> delimiters instead of {/} because the scopes aren't just block scopes, they isolate var as well; so I picked an arbitrary delimiter.)
When there are default parameter values, as you've described, there's an additional scope involved:
<<
let param1 = /*...the argument value provided for param 1 if any */;
let param2 = /*...the argument value provided for param 2 if any */;
<<
// Start of function code
var variable1;
let variable2;
// End of function code
>>
>>
The reason is that default parameter values are expressions, not just literals. For example:
function example(a = 1, b = a + 1) {
// ^^^^^−−−−−−−−−−−−− expression, not just literal
return a + b;
}
console.log(example()); // 1 + (1 + 1) = 3
console.log(example(2)); // 2 + (2 + 1) = 5
One reason that matters is that if there were just one scope for the parameter list and the function body, that would mean an expression in the parameter list could refer to hoisted variables and functions declared in the function body. The hoisted variables would just have the value undefined, so that wouldn't have been useful, but the hoisted functions would be initialized with their function bodies, leading to a situation like this:
// Doesn't work because of the additional scope
function example(a, b = blarg()) {
function blarg() {
return 42;
}
// ...
}
That causes a ReferenceError because the function body's scope isn't available in the parameter list's scope.
IIRC there were arguments for and against and a fair bit of discussion, but in the end the decision was to put the parameter list in its own scope to prevent that and other oddities.
Hope somebody finds the time to explain little about functions in functions and scoping.
I am trying to understand little more on functions and scope of variables and found a quite good tutorial, but this part I just do not get.
The task:
Create a function sum that will work like that: sum(a)(b) = a+b and accepts any number of brackets. Examples:
sum(1)(2) == 3
sum(5)(-1)(2) == 6
The solution:
function sum(a) {
var sum = a;
function f(b){
sum += b;
return f;
}
f.toString = function() { return sum };
return f; //line 12
}
alert( sum(1)(2) ); // 3e
The Explanation:
To make sum(1) callable as sum(1)(2), it must return a function.
The function can be either called or converted to a number with valueOf.
The solution is really self-explanatory:
My interpretation:
This f in function f(b) returned to the scope, which is from line 02 - 12.
The f in f.toString, is the currently returned f from function(b)
The next return f returns to the scope which is outside the function sum(a).
Problem:
I cannot figure out, where I need to think differently, because like I described above, the function would not be called again, so where is the part of the code, that make the 'several parentheses' possible?
Moreover, did I correctly assume where the fs are returned? Would be great if somebody would give some explanations.
The function sum returns a function, which we refer to as f.
The function f also returns a function: in fact, the function f returns itself.
When the function f is defined inside of sum, it gets permanent access to all variables currently visible in the scope chain. Here, it includes the locally-defined variable sum (the local running sum tally) and f (the function itself). (A "closure" is what we call the functional code of f along with all its in-scope variables.)
Because f returns itself, you can chain f with repeated calls:
var this_is_f = sum(1);
var same_f_again = this_is_f(2);
var f_a_third_time = same_f_again(3);
Or simply:
sum(1)(2)(3);
It is important to note that in my first example, I don't create new functions; instead, I just refer to the exact same function object with three different identifiers.
Each call to sum creates a brand-new f with a new local sum in its scope (here, I mean the local sum defined on the first line of the function named sum). However, calling the function sum does not clobber any old f, because each call to sum instantiates a new f (and knows nothing about any other fs that have been created on prior calls to sum). That way, you can have multiple tallies running:
var first_tally = sum(1)(2); // first: 3
var second tally = sum(4)(5); // second: 9
first_tally(3); // first: 6
second_tally(6); // second: 15
The reason you're able to see a meaningful result at any time is that f stingifies to the value of sum, instead of showing you its source code.
If you take this code and simplify it to the bare minimum I would be easier to understand. Take a function add that sums only 2 numbers:
function add(x,y) {
return x + y;
}
The above is a "normal" function. If you don't pass all the arguments you'll get unexpected results.
Now, if you want a function that adds 2 to any number, you could partially apply an argument to add, for example:
function add2(x) {
return add(2, x);
}
But in JavaScript we have first class functions (objects that can be passed around), so a function can take functions as inputs and return other functions. This is where "currying" comes in handy. While "partial application" lets you fix function arguments, "currying" takes a function of many arguments and breaks it down into a function of a single argument that returns another function of one single argument until all the arguments have been evaluated, in order, and then returns the result. For example:
function add(x) {
return function(y) {
return x + y;
}
}
Now you can create a function add2 by currying the function add:
var add2 = add(2);
add2(1); //=> 3
The normal function and the curried one have equivalent computations where:
add(1, 2) === add(1)(2)
This is what makes "several parentheses" possible.
In JavaScript "scope" and "closure" refer to functions but they're different concepts. A "scope" determines the reach/privacy of your variables while a "closure" lets you encapsulate code and carry it around. In the curried function above the variable x is kept in memory through closure because it's referenced inside the returned function object.
A particular limitation of "currying" is that you can't have functions of dynamic arity; the number of arguments must be fixed. This is not the case in the code you post where your sum function must be able to add a new number to the previous sum indefinitely.
Similarly to "currying" there's the idea of "generators"; a pattern to model sequences of lazy computation, in this case just adding a number to the previous sum on demand.
function sum(a) { // begin closure
var sum = a; // kept in memory...
function f(b) {
sum += b; //...because you use it here
return f;
}
f.toString = function() { return sum };
return f;
} // end closure
A different (maybe more clear) way to express your code would be to return an object to chain the computations, where you can either add a new number to the previous sum, or get the total sum so far:
function add(a) {
var sum = a;
return {
plus: function(b) {
sum += b;
return this;
},
sum: function() {
return sum;
}
}
}
add(1).plus(2).plus(3).sum(); //=> 6
In your code the returned function f acts as plus and toString as sum which retrieves the value.
Line 01-13 defines the function sum within the global scope.
Line 15 calls sum and changes scope to inside the function.
The variables a and sum and the closure function f are all defined in the function's scope - with the sum variable hiding the function definition from the global scope.
I'll skip over the toString bit here as its not important till later (when it gets very important).
The function sum finally returns a reference to the closure function f to the global scope as an anonymous function (since f can only be referenced by name from within its containing function's scope).
Back to line 15 - sum(1)(2) is the same as (sum(1))(2) and since sum(1) returns f then this can be reduced to (f)(2) or, more simply, f(2).
Calling f(2) adds 2 to sum - sum is defined in two scopes: as a function in the global scope; and as a variable (currently assigned the value of 1) within that function which hides the definition from the global scope - so, in f, the sum variable is set to 1+2=3.
Finally, in f, the function returns itself.
Back, again, to line 15 - f(2) returns f (although the named function f cannot be referenced in the global scope and, again , is treated as an anonymous function)
alert() is processed and the anonymous function (referred to as f) is converted to a string to be alerted; normally when alert() is called on a function it will display the source for the function (try commenting out Line 10 to see this). However, since f has a toString method (Line 10) then this is invoked and the value of sum (as defined in the function containing f) is returned and 3 is alerted.
Let's step through the function line by line:
function sum(a) {
This part is pretty self-explanatory; we have a function named sum which accepts an argument a.
var sum = a
Here we have a local variable called sum that is set to the value of the argument that is passed in.
function f(b) {
sum += b
return f
}
This is an inner function called f that accepts an argument called b. This b is then added to the value of sum from the outer scope (i.e., inside the scope of the function that is also called sum). After that, the function returns itself.
f.toString = function() { return sum }
This is the fun part! When you normally console.log a function, it will just spit out the function's source. Here we are redefining the toString method to instead be a function that spits out the value of sum. This is why you end up seeing the running total that is displayed instead of the function's source even though what you are returning is still a function.
Finally we have:
return f
So you basically have a function sum, returning a function that returns itself. The function sum basically sets everything up, but after calling sum(3), you then work with f, which you repeatedly call.
So the first time you call sum, you essentially get back this function:
function f(b) {
sum += b; //value of sum is 3
return f;
}
In this context, the value of sum will be the value of a that you passed into the initial call of the function sum. However, since the toString of f has been redefined, you only see the value 3. Then let's say you do sum(3)(4).
You get back, as before:
function f(b) {
sum += b; //value of sum is 3
return f;
}
But then you are actually calling f with an argument of 4 (basically f(4)). Since f is an inner function, it has full access to the scope of its parent function. This parent function (sum) is maintaining the the running total in a variable called sum, which is accessible to f. So when you now call f(4), you have b set to 4 and sum having a value of 3:
function f(b) { //b is 4
sum += b; //value of sum is 3 + 4, which is 7
return f;
}
So with each subsequent pair parentheses you are making repeated calls to the same f which is maintaining a running tally.
Another way is to think of sum as a kind of factory that can give you different f's, all of which keep their own running tallies (basically behaving like accumulators):
var firstSum = sum(4);
var secondSum = sum(2);
firstSum(5); //equivalent to sum(4)(5) returns 9
secondSum(2); //equivalent to sum(2)(2) returns 4
There are 3 concepts being played here
closures (no scope).
functions are first class OBJECTS in javascript (allows for chaining f(a)(b)(c)). There's no need to save a handle to the function to call it later.
I'll give you a run-down and then add some extra explanations afterwards
function sum(a) {
// when sum is called, sumHolder is created
var sumHolder = a;
// the function f is created and holds sumHolder (a closure on the parent environment)
function f(b) {
// do the addition
sumHolder += b;
// return a FUNCTION
return f;
}
// change the functions default toString method (another closure)
f.toString = function() {return sumHolder;}
// return a FUNCTION
return f
}
/*
* ok let's explain this piece by piece
*
* you call sum with a parameter
* - parameter is saved into sumHolder
* - a function is returned
*
* you call the returned function f with another parameter
* EXPLANATION: { sum(a) } returns f, so let's call f as this => {...}()
* - this private (priviledged) function adds whatever it's been passed
* - returns itself for re-execution, like a chain
*
* when it all ends {{{{}(a)}(b)}(c)} the remainder is a FUNCTION OBJECT
* this remainder is special in that it's toString() method has been changed
* so we can attempt to cast (juggle) it to string for (loose) comparison
*
*/
The concept behind closures is quite easy to understand but it's application make's your head spin until you get used to the idea that there is no function scope in javascript, there is closures and these are powerfull critters indeed
// this anonymous function has access to the global environment and window object
(function()
{// start this context
var manyVars, anotherFunc;
function someFunc() {
// has access to manyVars and anotherFunc
// creates its own context
};
anotherFunc = function () {
// has access to the same ENVIRONMENT
// creates its own context
};
}// whatever is in these keys is context that is not destroyed and
// will exist within other functions declared inside
// those functions have closure on their parent's environment
// and each one generates a new context
)();
Functions are first class objects. What does this mean? I'm not sure myself but let me explain with some further examples:
// how about calling an anonymous function just as its created
// *cant do the next line due to a language constraint
// function(){}()
// how about a set of parens, this way the word "function" is not the first expression
(function(){}());
// the function was created, called and forgotten
// but the closure inside MAY STILL EXIST
function whatDoIReturn() {
return function (){alert('this is legal');return 'somevalue';}();// and executed
}// returns 'somevalue'
Don't take this word for word. Go look for other people's code, check the Crockford and ask any and all questions that come up
What is the relationship between a function and a value? I thought that a function was a type of value; however, functions both contain values (arguments) and return values too.
I'm (obviously) new to programming, and want to ensure that I have a solid conceptual foundation as I move my way through JavaScript.
Functions do things. Variables hold values (data).
A function can accept data as arguments. A function can also return data, but does not have to. Consider this function which just adds two numbers together:
function addNumbers(numberA, numberB) {
var total = numberA + numberB;
console.log(total);
}
This is a function which accepts two arguments. Within the function's code block, those arguments' values are assigned to the variables numberA and numberB. The function's code creates another variable, total, and assigns the value of numberA added to the value of numberB. The function then calls another function, console.log, with the value of total passed in as an argument.
Now, the function can also return values. Let's modify this function a bit:
function addNumbers(numberA, numberB) {
var total = numberA + numberB;
return total;
}
If you were to call this function now, you get back the value of total. If I were to run this:
console.log(addNumbers(5, 5));
You would see 10 in the console. My number literal values were passed as arguments to addNumbers. The function did its work and returned to me the value of its total variable. This value is now passed in as an argument to console.log.
If that isn't crystal clear yet, then please read other tutorials online before continuing.
Now, in JavaScript functions are just like anything else. You can assign them to variables as well!
var newAddNumbers = addNumbers;
console.log(newAddNumbers(5, 5)); // Also returns 10 in the console
When you type:
function someFunction () {
This is no different than:
var someFunction = function () {
The function itself is assigned to the variable someFunction. In our original example, the function itself was assigned to addNumbers. So yes, function is a type just like number, object, boolean, etc.
If I have a function:
function add(a, b) {
return a + b;
}
add is a function. All functions are values; I can place them in a variable or pass them as an argument, for example.
a and b are arguments of add, but the function has not been called, so they do not have values. Similarly, the function has been called, so it has no return value.
When I call the function:
add(1, 2);
The function executes with a and b initially set to 1 and 2 respectively for that invocation.
If I call it again with different arguments:
add(3, 4);
Then this time a and b are initially set to 3 and 4; however, these a and b not only have different values than the last time; they really are different variables. Every time you call a function, the arguments are essentially variables, which are local not only to that function but to that invocation of that function.
Background: I want to rewrite a library (which I did not write) to avoid having the Closure Compiler generate warnings with the advanced option. Per this question JavaScript “this” keyword and Closure Compiler warnings the answer was to rewrite the code using a closure. The intent is to avoid using the keyword this (which generates the compiler warnings).
As the library has a number of functions, I though it would be best for the new closure to return an object literal. I want to understand how this works and any possible ramifications. I therefore wrote the following (meaningless) example as a learning expercise (also here: jsFiddle):
var CurrencyObject = function(Amount) {
var money = Amount;
return {
"toCents": function() {
money *= 100;
return money;
},
"toDollars": function() {
money /= 100;
return money;
},
"currentValue": money // currentValue is always value of Amount
};
}; // end currencyObject
var c1 = CurrencyObject(1.99); // what's the difference if the syntax includes `new`?
alert('cents = ' + c1.toCents() + '\ncurrent money = ' + c1.currentValue + '\ndollars = ' + c1.toDollars() + '\ncurrent money = ' + c1.currentValue);
var c2 = CurrencyObject(2.99);
alert('cents = ' + c2.toCents() + '\ncurrent money = ' + c2.currentValue + '\ndollars = ' + c2.toDollars() + '\ncurrent money = ' + c2.currentValue);
alert('cents = ' + c1.toCents() + '\ncurrent money = ' + c1.currentValue + '\ndollars = ' + c1.makeDollars() + '\ncurrent money = ' + c1.currentValue);
Q1: Why isn't currentValue updated after the call to toCents? (I'm going to guess that it is because currentValue is a literal(?) that it is initialized when CurrencyObject is first executed. If that's the case, what's the syntax for also returning the property currentValue?)
Q2: This syntax (with new) var c1 = new CurrencyObject(1.99); does not change the code's behavior in a way that I can detect, yet I assume there is a difference. What is it?
Q3: When c2 is instantiated, are copies of the functions being created or will c1 and c2 share the same (function) code? (If copies of the functions are being created, what changes do I make to avoid that?)
TIA
BTW: In the event someone is wondering, the symbols in the object literal are quoted to avoid having the Closure-Compiler rename them.
Q1: You've created two variables that contains separate copies of the Amount. One is in the money variable captured in the closure. The other copy is in the currentValue property of your returned object. Those are separate variables that have no connection to one another, other than the initial value of currentValue is initialized with the value of the money variable.
To work-around this issue, you have to settle on only have one place that you store your currentValue and refer to it there. You could only use the money local variable in the closure, but that would require changing the currentValue property to be a getter function (that retrieves the money value) rather than a direct data property.
Or, you could get rid of the money closure variable and only use the currentValue property. That would require you to use this to get that property in the toCents and toDollars methods. In my opinion, the cleaner way to do this would the latter (using this to reference the object's own properties). I have no idea why closure wouldn't want you to do that.
Q2: When you explicitly return an object from a constructor, then it no longer matters whether the constructor is called directly as a function or with the new operator. As you have observed, both create the same result.
Q3: Since your functions are anonymous, each new instantiation will create a new anonymous function object. How efficient or inefficient that is will depend upon the javascript implementation. You could make there only be one function by declaring your functions to be local named functions and referring to that name. Then, you could guarantee that no new function was created.
UPDATE:
I branched your fiddle, and added a couple of methods that all instances will in fact share (ie: no new function objects will be created for each instance): the methods that convert the amount into Euro's or Pounds, for example. I've also omitted the money variable, because it's simply not necessary. To avoid having to use this as much as possible, I've also assigned the returned object to a variable within the closure scope, so that all methods can reference their parent object via that variable name, rather than having to rely on this.Shared methods, however, will still have to use this occasionally, because they were declared in a "higher" scope, and don't have access to the returnObject variable, simply because it doesn't exist in their scope. Lifting the returnObject variable declaration is no solution in case you were wondering, because then you'll soon find out that you can't create more than 1 instance of the currency object.Lastly, I've changed the name of the "constructor" to start with a lower case. Technically, your function is not a constructor any longer, and convention is that it therefore can't start with an upper-case letter... Let me know if anything I explained here, or any of my suggested changes are still unclear to you.
The currentValue isn't updated because you changed the money variable's value by doing: money *= 100;. This statement multiplies the money value and assigns it to the same variable. Since this is a primitive, currentValue has its own copy of this value, they're not linked in any way.Suggestions: use return money/100; to keep the value of money constant. As it now stands calling the toCents method twice is the same as multiplying the original amount by 10,000. To update/set the currentValue on each call to whatever you want it to be, add: this.currentValue = money*100;, which is a little dangerous, or giving your closure access to its own literal by using a named reference (which is safer, but a bit more verbose):
var someClosure = function (amount)
{
var money = amount;//redundant: you can use amount, it's preserved in this scope, too
var me = {currentValue:amount,
toCents: function()
{
me.currentValue = money*100;//<-- use me to refer to the object itself
return amount/100;
}
};
return me;
}
There is no reason to use the new keyword: the object that is created by this "constructor" is an object literal, it has only 1 prototype (Object.prototype, and no explicit constructor name). Adding new will make this point to a new object in the function itself, but since you're not using it, and your function returns another object, the object is never returend.
Strictly speaking: some JS engines will create new function objects for each new instance. Some modern objects optimize this, and will in fact only create 1 function object. To be on the safe side, you can wrap another closure around things, to make sure there is only 1 function, regardless of what engine runs your code:
var someObjectGenerator = (function()
{
var oneOffFunction = function()
{
console.log('this function will only be created once');
}
return function(amount)
{
return { foo:oneOffFunction,
toCents: function()
{
return amoutn/100;
}
};
};
};
Of course, functions that are created in a scope above the one that has the money or amount variable won't have access to that variable, so in that case you'll have to create new functions... but JS objects are very cheap, so don't worry about it that much. Again, most engines deal with this rather well.
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