1

I thought I understood closures but I guess not. Here is a code sample that shows the issue I run into. I would expect the code to print 'text' to the console.

var inner = function() {
 console.log(text);
};
var outer = function(cb) {
 var text = 'text';
 cb();
};

I run the outer function with the inner function as a cb. In this case, I get var text is undefined. I thought that the inner function would still have a reference to the text variable because of js closure.

//Run outer with a cb of inner.
outer(inner);

Tried using an anonymous function as a cb and gives the same error of text being undefined.

//Anonymous
outer(function() {
 console.log(text);
});

Any ideas what I'm missing here? I am using closure in other areas of my program without problems, but clearly I don't fully understand what's going on.

asked Apr 5, 2016 at 18:45

5 Answers 5

3

The problem here is less the result of closures as it is scope... and I prefer to think of JavaScript scope in terms parent/child relationships.

Any scoped entity (e.g. a function) has access to things defined in its inherited "parent" scopes (visibility travels upwards) -- but "parent" scopes cannot see inside of "child" scopes, and children of the same scope cannot see inside one another.

enter image description here

The image above is generic and shamelessly stolen from Google Images, but serves to explain that "A" is the parent scope; "B" and "C" were defined within the parent scope. "D" and "E" are defined within the scope of "B" -- so "C" cannot see "D" or "E".

In your example, the "parent" scope is the context in which these two functions have been defined (presumably window). Anything defined inside the scope (context) of one of the "children" methods can see the things defined in the scope (context) above it -- so the code inside outer() is aware that inner() exists (both were defined in the parent scope), but neither function can see what exists inside the other. (Note: the parent scope (presumably window) also cannot see what was defined inside each of these functions; it only knows the functions exist.)

But because the visibility only travels upwards, the scope inside inner() does not know about text because it was defined inside outer().

answered Apr 5, 2016 at 19:01
Sign up to request clarification or add additional context in comments.

Comments

2

text is undefined - this isn't a closure issue, it's an issue of not passing a parameter to your callback:

var outer = function(cb) {
 var text = 'text';
 cb(text); //note the parameter pass in here
};
outer(function(textParam) { //and now the callback passed in accepts a param
 console.log(textParam) //name this param whatever you want!
});
answered Apr 5, 2016 at 18:48

Comments

1

There's no (relevant) closure when calling cb inside outer.

If you created inner inside outer you'd be closing over text, and you would see its value when calling inner–but you're not.

The text inside inner is the global text.

answered Apr 5, 2016 at 18:48

1 Comment

Thank you, this clarified the problem for me. I will have to take a closer look at closures as well.
0

Closures allow functions to access variables in the scope in which they are defined, not the scope in which they are called.

Modifying your example, the following would print "changed text".

var text = 'some text';
var inner = function() {
 console.log(text);
};
text = 'changed text'
var outer = function(cb) {
 cb();
};
outer(inner);
answered Apr 5, 2016 at 19:09

Comments

0

You should also study the term Lexical Scoping to understand the situation. The scope of a variable/function is defined by its location within the source code.

A closure is created when a function is declared within a second/outer function and then returned from that function (second/outer). In your case, the inner function is not declared inside the outer function.

You could re-arrange you code to form a closure as:

function outer() {
 var text = 'text';
 function inner(){
 console.log(text);
 };
 return inner;
}
var foo = outer();
foo(); // text
answered Apr 5, 2016 at 20:29

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.