Why is "reduce" and "map" considered closures in javascript? - javascript

I was going over closures and usually I look at a closure as a function that has been returned from another function or is a function that is set to a global while inside another function so that the new function (returned function or global variable) has a reference to the variables inside the initial enclosing function where it was created. Recently, someone told me that the map or reduce function form closures. These return a value or values and no function whatsoever. I dont see how this method forms a closure when all you have is a callback. In fact, MDN states that the reduce function returns a "value" and the map function returns an array. So where is the closure? Can someone explain this?

A function defined inside a function ends up being a closure by definition if local variables are present at the surrounding function and they're used inside the closure.
For example:
function boil(ocean) {
var boiling = 100.0;
return ocean.map(function(h2o) {
return h2o.temp >= boiling ? 'vapour' : 'water';
});
}
The boiling variable here is defined in the main function and used within the function passed to map. Callback functions make the closure behaviour more obvious since they're used in a different context, but the same principle applies.

The "closure" is the callback function. According to MDN:
A closure is the combination of a function and the lexical environment within which that function was declared.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
So when you write something like this:
array.map(function(object) {
// do something
});
That function that you pass in becomes a closure because it gains access to the scope that was present when array.map was called. That's just how JavaScript works.

Thank you all for your responses to the question. With these and the chrome debugger I have come to the conclusion. As Alnitak stated, "
It's a closure iff it accesses variables from that outer scope. Just having the ability to access them is insufficient." This is an important point that I was missing. Also, you can see in the scope section of the sources tab in chrome debugger variables included through closure. So, looking at the following example we can see exactly what closure is:
routerAction: function () {
var name = "alex";
var alex = function(v){
debugger;
console.log("this is var ", name);
}
alex(); // if name was passed and then printed it would be local
// not a closure
}
Functions get their scope from global and local and closure variables.
When you pass "name" into the alex function as a parameter it becomes a local variable so there is no closure. So, if I passed it to alex and console logged "v" where name is, no variables are referenced through a closure. However, since name is defined outside the scope of function alex and then used within, it is scoped through closure (this can be seen in in the scope section of the chrome debugger). By this same logic, if the array that you are operating on (using map or reduce )is defined inside a function, the callback has to form a closure iff the array is referenced inside the callback. If the parameters are just brought in through arguments, none of the variables are accessed through a closure, they are all local variables.

Related

Does this function have closure over this block?

I am experimenting with closures but rather than enclosing a function within a function, I enclosed a function within a block. Since functions are not blocked-scoped and will be hoisted outside of the block I assumed that it wouldn't have access to the scope within the block. Yet, in this case, the function returns the block-scoped variable. Does this mean that the function is a closure?
{
let a = 'hi'
function test() {
return a
}
}
test() // hi
I'd be happy to call it a closure, at least according to Wikpedia's definition:
Operationally, a closure is a record storing a function together with an environment. The environment is a mapping associating each free variable of the function (variables that are used locally, but defined in an enclosing scope) with the value or reference to which the name was bound when the closure was created. Unlike a plain function, a closure allows the function to access those captured variables through the closure's copies of their values or references, even when the function is invoked outside their scope.
In your function test, the variable a is a free variable, used by the function but not defined inside the function. When you called the function outside the block, it retained the value of a. So, you've met the essential points of the definition of closure (according to Wikipedia).
Of course, you asked the question because it's kind of tricky. Normally with closures, we define a function inside an environment and then "export" it out by binding the function object to a name that has a wider scope. Because of the way JavaScript treats function declarations defined in a block (see Code Maniac's link to the ECMAScript specification on handling block-scoped function declarations) you do get this effect! So it's kind of a closure, even though you never explicitly exported the function.
Of course if you had written
{
let a = 'hi'
let test = () => a
}
test()
you get an error.
But this works:
let b;
{
let a = 'hi'
let test = () => a
b = test
}
b() // "hi"
so yes, the block is acting as the non-local environment from which variables can be captured. I'm thinking yes, it's okay to speak of this as being a closure, because it acts like one (even if this behavior comes from a pre-ECMAScript 2015, "optional", and non-strict treatment of function declarations inside of blocks). If it walks like a duck, and all that.

Callback definition closure issue

I run into a bit of confusion regarding scoping with respect to where a callback is defined.
function test(){
var b = 3
var fun = function(){
var printingFunction = function(){
console.log(b)
}
printingFunction()
}
return fun
}
test()() //prints 3, as expected because of closures
However, the following doesnt work
function test(){
var b = 3
var fun = function(cb){
cb()
}
return fun
}
test()(function(){console.log(b)}) //b is not defined
I would expect that since the function is passed as an argument and has not been defined before, its definition takes place inside 'fun' and therefore it would have access to b. Instead, it looks a lot like the function is first defined in the scope where its passed and THEN passed as an argument. Any ideas/pointers?
EDIT: Some extra pointers.
someFunction("a")
We couldn't possibly claim that "a" is a definition. What happens here implicitly is that "a" is assigned to a variable named by the argument name so var argumentNameInDefintion = "a". This happens in the body of someFunction.
Similarly we cant claim {} is a definition in : someFunction({}). So why would:
someFunction(function(){})
decide that function(){} is a definition is beyond me. Had it been
var a = function(){}
someFunction(a)
everything would make perfect sense. Maybe its just how the language works.
Scoping in JavaScript is lexical. If you look at your examples, you can see that where printingFunction is defined, lexically (e.g., in the source text) b is declared in a containing scope. But in your second example, it isn't. That's why b can't be resolved in your second example but can in your first.
The way it works is that when a function is created, it has a reference to a conceptual object containing the variables and such in the scope in which it's created (which has a fancy name: "Lexical Environment object"); and that object has a reference to the one that contains it. When looking up a variable reference, the JavaScript engine looks at the current lexical environment object and, if it finds the variable, uses it; otherwise, it looks to the previous one in the chain, and so on up to the global one.
More details can be found:
In this SO question's answers
In this post on my anemic little blog
The issue stems from me not understanding that function(){} on its own is a definition and so is "a" and {}. Since these are definitions then the definition scope of the function passed is appropriately placed where it is and the world makes sense again.
In first case, it is forming a closure and has access to the variable "b" but in second case it does not form a closure at all. If you put a debugger just before the cb() inside the function, you will notice that there is no closure formed and the reason of that being the callback function is suplied to the function as an argument and it becomes local to that function which does not have any knowledge of the variable b.
Think of it as two different functions, one in which it has a local variable "b" and in other no local variable but we are trying to access it which throws the reference error.

What is missing from this description for nested functions and closures at Mozilla Developer Network?

I feel like there is something missing from it. Here it is:
Nested functions and closures
You can nest a function within a function. The nested (inner) function is private to its containing (outer) function. It also forms a closure. A closure is an expression (typically a function) that can have free variables together with an environment that binds those variables (that "closes" the expression).
Since a nested function is a closure, this means that a nested function can "inherit" the arguments and variables of its containing function. In other words, the inner function contains the scope of the outer function.
To summarize:
The inner function can be accessed only from statements in the outer
function.
The inner function forms a closure: the inner function can use the arguments and variables of the outer function, while the outer
function cannot use the arguments and variables of the inner
function.
The following example shows nested functions:
function addSquares(a,b) {
function square(x) {
return x * x;
}
return square(a) + square(b);
}
a = addSquares(2,3); // returns 13
b = addSquares(3,4); // returns 25
c = addSquares(4,5); // returns 41
Since the inner function forms a closure, you can call the outer function and specify arguments for both the outer and inner function:
function outside(x) {
function inside(y) {
return x + y;
}
return inside;
}
fn_inside = outside(3); // Think of it like: give me a function that adds 3 to whatever you give it
result = fn_inside(5); // returns 8
result1 = outside(3)(5); // returns 8
Closures are definitely a topic that is confusing at first, but really it boils down to this:
ANYTIME you have a nested function, you technically have a closure.
Just because you have a closure doesn't necessarily mean that your code will be affected in any significant way.
3. When a nested function relies on variables declared in a higher function (ancestor function) AND the nested function will have a lifetime that is LONGER than the function where those relied on variables were declared, you have a closure situation that needs understanding.
Those variables (used in the nested function, but declared in the higher order function, a.ka. free variables) cannot be garbage collected when the function in which they were declared completes because they are needed by the nested function which will outlive its parent/ancestor. This "outliving" can be caused by the nested function being returned to an even higher order caller by the nested function's parent or the nested function is assigned to another object (like a DOM object).
When this happens, a closure is created around the free variable and that variable's scope is now shared by any other in-memory function that relies on it as well. This causes a shared scope and is usually where confusion by a function that was supposed to get its own value does not. In those cases, modifying the inner function to receive a COPY of the ancestor's free variable can solve this confusion.

Is a function return necessary to be called a Closure

Hey i came across this video on youtube http://www.youtube.com/watch?v=KRm-h6vcpxs
which basically explains IIFEs and closures. But what I am not understanding is whether i need to return a function in order to call it a closure.
E.x.
function a() {
var i = 10;
function b() {
alert(i);
}
}
in this case can i call it a closure as it is accessing the 'i' variable from the outer function's scope or do i need to return the function like this
return function b(){alert(i);}
A closure is simply a function which holds its lexical environment and doesn't let it go until it itself dies.
Think of a closure as Uncle Scrooge:
Uncle Scrooge is a miser. He will never let go of his money.
Similarly a closure is also a miser. It will not let go of its variables until it dies itself.
For example:
function getCounter() {
var count = 0;
return function counter() {
return ++count;
};
}
var counter = getCounter();
See that function counter? The one returned by the getCounter function? That function is a miser. It will not let go of the count variable even though the count variable belongs to the getCounter function call and that function call has ended. Hence we call counter a closure.
See every function call may create variables. For example a call to the getCounter function creates a variable count. Now this variable count usually dies when the getCounter function ends.
However the counter function (which can access the count variable) doesn't allow it to die when the call to getCounter ends. This is because the counter function needs count. Hence it will only allow count to die after it dies itself.
Now the really interesting thing to notice here is that counter is born inside the call to getCounter. Hence even counter should die when the call to getCounter ends - but it doesn't. It lives on even after the call to getCounter ends because it escapes the scope (lifetime) of getCounter.
There are many ways in which counter can escape the scope of getCounter. The most common way is for getCounter to simply return counter. However there are many more ways. For example:
var counter;
function setCounter() {
var count = 0;
counter = function counter() {
return ++count;
};
}
setCounter();
Here the sister function of getCounter (which is aptly called setCounter) assigns a new counter function to the global counter variable. Hence the inner counter function escapes the scope of setCounter to become a closure.
Actually in JavaScript every function is a closure. However we don't realize this until we deal with functions which escape the scope of a parent function and keep some variable belonging to the parent function alive even after the call to the parent function ends.
For more information read this answer: https://stackoverflow.com/a/12931785/783743
Returning the function changes nothing, what's important is creating it and calling it. That makes the closure, that is a link from the internal function to the scope where it was created (you can see it, in practice, as a pointer. It has the same effect of preventing the garbaging of the outer scope, for example).
By definition of closure, the link from the function to its containing scope is enough. So basically creating the function makes it a closure, since that is where the link is created in JavaScript :-)
Yet, for utilizing this feature we do call the function from a different scope than what it was defined in - that's what the term "use a closure" in practise refers to. This can both be a lower or a higher scope - and the function does not necessarily need to be returned from the function where it was defined in.
Some examples:
var x = null;
function a() {
var i = "from a";
function b() {
alert(i); // reference to variable from a's scope
}
function c() {
var i = "c";
// use from lower scope
b(); // "from a" - not "c"
}
c();
// export by argument passing
[0].forEach(b); // "from a";
// export by assigning to variable in higher scope
x = b;
// export by returning
return b;
}
var y = a();
x(); // "from a"
y(); // "from a"
The actual closure is a container for variables, so that a function can use variables from the scope where it is created.
Returning a function is one way of using it in a different scope from where it is created, but a more common use is when it's a callback from an asynchronous call.
Any situation where a function uses variables from one scope, and the function is used in a different scope uses a closure. Example:
var globalF; // a global variable
function x() { // just to have a local scope
var local; // a local variable in the scope
var f = function(){
alert(local); // use the variable from the scope
};
globalF = f; // copy a reference to the function to the global variable
}
x(); // create the function
globalF(); // call the function
(This is only a demonstration of a closure, having a function set a global variable which is then used is not a good way to write actual code.)
a collection of explanations of closure below. to me, the one from "tiger book" satisfies me most...metaphoric ones also help a lot, but only after encounterred this one...
closure: in set theory, a closure is a (smallest) set, on which some operations yields results also belongs to the set, so it's sort of "smallest closed society under certain operations".
a) sicp: in abstract algebra, where a set of elements is said to be closed under an operation if applying the operation to elements in the set produces an element that is again an element of the set. The Lisp community also (unfortunately) uses the word "closure" to describe a totally unrelated concept: a closure is an implementation technique for representing procedures with free variables.
b) wiki: a closure is a first class function which captures the lexical bindings of free variables in its defining environment. Once it has captured the lexical bindings the function becomes a closure because it "closes over" those variables.”
c) tiger book: a data structure on heap (instead of on stack) that contains both function pointer (MC) and environment pointer (EP), representing a function variable;
d) on lisp: a combination of a function and a set of variable bindings is called a closure; closures are functions with local state;
e) google i/o video: similar to a instance of a class, in which the data (instance obj) encapsulates code (vtab), where in case of closure, the code (function variable) encapsulates data.
f) the encapsulated data is private to the function variable, implying closure can be used for data hiding.
g) closure in non-functional programming languages: callback with cookie in C is a similar construct, also the glib "closure": a glib closure is a data structure encapsulating similar things: a signal callback pointer, a cookie the private data, and a destructor of the closure (as there is no GC in C).
h) tiger book: "higher-order function" and "nested function scope" together require a solution to the case that a dad function returns a kid function which refers to variables in the scope of its dad implying that even dad returns the variables in its scope cannot be "popup" from the stack...the solution is to allocate closures in heap.
i) Greg Michaelson ($10.15): (in lisp implementation), closure is a way to identify the relationship betw free variables and lexical bound variables, when it's necessary (as often needed) to return a function value with free variables frozen to values from the defining scope.
j) histroy and etymology: Peter J. Landin defined the term closure in 1964 as having an environment part and a control part as used by his SECD machine for evaluating expressions. Joel Moses credits Landin with introducing the term closure to refer to a lambda expression whose open bindings (free variables) have been closed by (or bound in) the lexical environment, resulting in a closed expression, or closure. This usage was subsequently adopted by Sussman and Steele when they defined Scheme in 1975, and became widespread.

Is it good to write javascript functions inside functions and not use 'new' on the main function?

I now know this works:
function outerfunction(arg1, arg2, arg3) {
var others;
//Some code
innerFunction();
function innerFunction() {
//do some stuff
//I have access to the args and vars of the outerFunction also I can limit the scope of vars in the innerFunction..!
}
//Also
$.ajax({
success : secondInnerFunction;
});
function secondInnerFunction() {
// Has all the same benefits!
}
}
outerFunction();
So, I am not doing a 'new' on the outerFunction, but I am using it as an object! How correct is this, semantically?
There doesn't appear to be anything wrong with what you're doing. new is used to construct a new object from a function that is intended as a constructor function. Without new, no object is created; the function just executes and returns the result.
I assume you're confused about the closure, and how the functions and other variables belonging to the function scope are kept alive after the function exits. If that's the case, I suggest you take a look at the jibbering JavaScript FAQ.
You are not using the outer function as an object. You are using it to provide a closure. The border line is, admittedly, thin, but in this case, you are far away from objects, since you do not pass around any kind of handle to some more generic code invoking methods, all you do is limiting the scope of some variables to the code that needs to be able to see them.
JFTR, there is really no need to give the outer function a name. Just invoke it:
(function() { // just for variable scoping
var others;
...
})()
I do this sort of thing all the time. Yes - javascript blurs the boundary between objects and functions somewhat. Or perhaps, more correctly, a javascript function is just an object that is callable. You would only really use the 'new' prefix if you wanted to have multiple instances of the function. My only suggestion here is that its usually considered good practice to call a function after you've declared it (you are calling the innerFunction before it has been declared) - although that could be considered nit-picking.
This is a valid example.
Functions in JavaScript are first order objects. They can be passed as an argument, returned from a function or even set to a variable. Therefore they are called 'lambda'.
So when you are directly using this function (without new keyword) you are directly dealing with the function as an object. When u are using new keyword, you are dealing with an object instance of the function.

Categories

Resources