With javascript closures and callbacks, I am confused on the difference between why the parameters that a named, nested function take are different (inherited from the outer function?) than a closure's parameters. For example:
var filter = function (collection, test) {
var newArray = [];
each(collection, function (value) {
if (test(value)) {
newArray.push(value);
}
});
return newArray;
};
The filter function operates on the each function. What input does the "value" parameter (in each) correspond to? Does a callback function's parameter automatically line up with filter's first parameter because they are both the first parameter of their respective functions? If the outer function and the inner one both accepted another parameter, would those line up because of their position as well? The parameter relationship between the inner/outer function here seems to be different from a closure's parameter (the closure seems to accept a new parameter; its parameters don't line up with the outer one's parameters) For example:
var outer = function(par1, par2) {
var hold = par1 + par2;
function inner(par3) {
return par3 + par1 + par2;
}
return inner;
};
var closure = outer (5,4);
closure(2);
I see that the inner function is returned from the outer function (when stored in another variable) and takes its own parameter separate from the outer function.
Do named/established functions inherit their parameter correspondence from their enclosing functions?
Do callback functions take on their own parameter - separate from their enclosing function - because they are returned out of that function and saved to a variable?
What input does the "value" parameter (in each) correspond to?
That depends on what each does. It isn't a standard JS global and you haven't shared your definition of it.
Does a callback function's parameter automatically line up with filter's first parameter because they are both the first parameter of their respective functions?
No. The arguments pass to any function are dependant on the code that calls that function.
If the outer function and the inner one both accepted another parameter, would those line up because of their position as well?
No.
Do named/established functions inherit their parameter correspondence from their enclosing functions?
No.
Do callback functions take on their own parameter - separate from their enclosing function
Yes
because they are returned out of that function and saved to a variable?
No. It is because they are functions.
function outer(foo, bar) {
console.log("Outer gets foo " + foo + " because foo is a argument of outer");
console.log("Outer gets bar " + bar + " because foo is a argument of outer");
return inner;
function inner(baz) {
console.log("Inner gets foo " + foo + " because foo is a variable still in scope");
console.log("Inner gets bar " + bar + " because bar is a variable still in scope");
console.log("Inner gets baz " + baz + " because baz is an argument of inner");
}
}
var returned_inner = outer(1, 2);
returned_inner(3);
With javascript closures and callbacks, I am confused on the difference between why the parameters that a named, nested function take are different (inherited from the outer function?) than a closure's parameters.
Your confusion problem springs from the simple fact that, most of the time, when you are using a callback, the function that actually calls it is written by someone else and you never look at it.
I think I can sum up the answer to all of the questions by saying that there is absolutely no requirement at all for the parameters of an inner function to have anything at all to do with the parameters of the enclosing function.
They are completely unrelated values.
For example:
function f(a, b, c, d, e) {
// You mentioned "named, nested" function in your question...
return function unusedName(x) {return x}
}
console.log(f(1, 2, 3, "four", 25/5)(100));
will display 100.
Of course, in reality, you would want the inner function to somehow or other use the parameters of the outer function, otherwise the parameters to the outer function are useless.
But there is no requirement that they "line up." How you create your closure, that is how your returned inner function decides to use the values from the environment provided by the outer function, is wholly up to you. The language itself enforces nothing.
Please consider changing most of the hypotheses in the question :-)
Identifier scope.
When javascript code uses an unadorned identifier (such as a variable name, the name of an object or the name of a function) inside a function, the javascript engine looks to see if the identifier is the name of a local variable, the name of a nested function defined within the same function body, or the name of a formal parameter. If not found it will search for the identifier, in the same manner, in a next most outer function (if a function searched is nested), or look for the identifier in global scope if the last function searched was itself global.
Hence there is no "lining up" of nested function parameters, there is just searching the scope chain. Outer function parameters, variables and named function definitions are all in scope of inner functions. There is no automatic "relationship" between formal parameter definitions in different functions unless planned by the programmer.
Closures
Be careful about categorizing functions as call backs or closures. Often a call back function forms a closure. In summary, a closure is caused by keeping a reference to a nested function after its outer function has returned. This can result from storing a reference to the inner function either before or after the outer function returns, or by passing a reference to the inner function to some other function for use as an asynchronous call back. A long as reference to the inner function is being held somewhere, any values it references within its scope chain cannot be made available for garbage collection because they are accessible.
forEach
The each function appears to be an iterator function being applied to the collection passed as an argument. Javascript supports a standardized forEach to iterated over Array, Map and Set objects. Please refer to documentation for further details on how it is called and calls back call back function.
Related
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.
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.
For example below is an anonymous function that has been placed in parentheses so now the function can be stored as a variable and called on else where as seen in number 2, However how can script number 1 be called to run? How can it be identified if it has no name? And how to change an anonymous function to a defined function?
**Number 1**
(function() {
// Do something
})();
**Number 2**
(var funcName = function() {
// Do something
})();
funcName();
The first function is called immediately because it is followed by () which calls a function.
Then if you were to remove the () from around the var statement (which is an error):
The second function is also called immediately, for the same reason.
The value stored in funcName (which is called as if it were a function, so will cause an error if it is not a function) is the return value of the second function (and is defined by the code you represented as // Do something — the "something" needs to include "return a function").
How can it be identified if it has no name?
Names are only really useful for use in debuggers (where they are very useful in stack traces and the like). For identifying a function to call, you access them like any other object or primitive (via a variable, property, etc). A function declaration just creates a variable with a matching name in the current scope.
Yes, these are anonymous functions, but they are also functions that are being called / invoked immediately, and hence don't need names to be referred to later.
There are many uses for Immediately-Invoked Function Expression (IIFE), but one is to use functions to establish namespaces that do not pollute global
So I'm reading through a book and it uses this method to overload functions-
function addMethod(object,name,fn){
var old = object[name];
object[name] = function(){
if (fn.length == arguments.length){
return fn.apply(this,arguments);
} else if(typeof old == 'function'){
return old.apply(this,arguments);
}
}
}
I have a few questions on this.
Why is fn.length still in scope when the function that's passed in is called? Shouldn't executing the addMethod have caused fn to go out of scope?
Why isn't the arguments referring to the arguments property of the anonymous function, rather than the arguments property of the fn function? (which it should I thought?)
The parameter "fn" is in scope because that's how JavaScript works. It's part of the closure around that anonymous function.
The anonymous function created is the replacement for the original function bound to the object with the property name "name". When called, it checks the arguments actually passed on that particular call by looking at the arguments object. If it sees that the number of arguments passed is the same as the number of formal parameters in the "fn" function, then it calls that function. Otherwise, it calls the previous ("old") function, if it exists and is a function.A key thing to understand is that the .length property of a function instance gives you the number of formal parameters in the declaration. For example, the .length for that "addMethod" function would be 3.
The way that closures work in JavaScript took me a while to really "get" because I was a C programmer for a long time. In languages like that, space for the function call local variables (etc) is allocated on the stack, and when the function exits it's all popped off the stack. JavaScript just doesn't work that way.
Wanting to get something straight here...so I have 2 questions
The function below creates a closure.
function Foo(message){
var msg = message;
return function Bar(){
this.talk = function(){alert(msg); }
}
};
Q: Which function is the closure, Foo or Bar?
I always thought the closure to be Foo, because it closes-over Bar once Bar is returned.
Next...
Below is the definition of an anonymous function:
()();
Q: Is the inner-function within this anonymous function also a closure?
(function(){ /* <-- Is this function also a closure? */ })();
You need to use first principles here. Javascript uses lexical scoping. This means the scope of an execution context is determined by how the code is defined (lexical).
I would say the definition of the function Bar is what causes the closure to be created, because msg is "closed-in" in the function.
The actual creation of the closure happens at runtime (which is somewhat of a tautological statement, since nothing in a computer program happens until it is run), because in order to determine the value of msg, in Bar, when Bar is executed, the interpreter needs to know the value of the variable when Foo is executed, and so on up the chain.
I'll give two answers to your question. The pedantic answer is: neither function by itself is the closure. It's the definition of variables within functions, combined with the execution context of functions when they are run, that is defines the closure. The common answer is: any function which closes over a variable is a closure (Bar in your case).
Consider the problem everyone encounters when using Javascript.
function A(x) {
var y = x, fs = [];
for (var i = 0; i < 3; i++) {
fs.push(function(){
console.log (i + " " + x);
})
}
fs.forEach(function(g){g()})
}
A('hi')
Most people would say this would produce the output 'hi 1' followed by 'hi 2' followed by 'hi 3'. However, it produces 'hi 3' 3 times. If just the definition of the function being added to the array, while using variables defined in the outer function, created the closure, how can this be?
It's because you need the execution context to define the closure, which doesn't happen until runtime. At the execution of the functions in the array, i has the value 3. In the forEach statement, that's the execution context, which is why the output always uses 3.
Bar is the closure.
We say that Bar closes over the variable msg in its environment.
Most often the word closure means: a function that uses at least one variable that’s defined in an enclosing scope, in an enclosing function.
To answer your second question: (function(){ ... })() is just what it looks like: one anonymous function, not two. Unless it’s nested inside another function, you generally wouldn’t call it a closure. However, functions nested inside that anonymous function can be closures (and often are).