Reputation: 14318
Why these two different code produce different results?
I mean foo2
, defined in the first code, and callback
, in the second code, are the same and they are executed in the same context, inside foo
.
First code:
var foo = function () {
var bar = 2;
var foo2 = function () {
console.log("bar: ", bar);
}
foo2();
}
foo() // 2
Second code:
var foo = function (callback) {
var bar = 2;
callback();
}
var callback = function () {
console.log(bar);
}
foo(callback); // ReferenceError: bar is not defined
Upvotes: 0
Views: 630
Reputation: 11
Because of function scope. (Meaning variables are only accessible within the scope of which they are declared, or declared within the scope chain (read on))
In your'e second example this becomes clare. callback() is declared in i global scope. When foo() then calls the callback(), the bar variable will not be visible since bar is declared inside another function (foo()). If you had declared bar outside the functions (in the global scope), it would be accessible from anywhere, meaning also inside any function.
This would work:
var bar = 2;
var foo = function () {
callback();
}
var callback = function () {
console.log(bar);
}
foo();
In your'e first example however you can access bar, even though it is not declared within foo2(). This is simply because if the javascript engine can't find the variable you try to use, it goes looking for that same variable in the "parent" function (or scope). This is referred to as the scope chain.
Upvotes: 1
Reputation: 65264
try
var foo = function (callback) {
var bar = 2;
callback(bar);
}
var callback = function (baz) {
console.log(baz);
}
foo(callback);
to see the difference: what is bar
inside foo, is baz
inside callback - previously, it was undefined
Upvotes: 0
Reputation: 754565
In the first case foo2
is defined inside of foo
hence it has access to all of the locals that foo
has access to. When it binds bar
it can't find it in foo2
, then looks in foo
and uses the one it finds there.
In the callback
case it's defined outside of foo
. Hence it can't see any of foo
locals and instead concludes the value is undefined
Upvotes: 1
Reputation: 2503
In the two samples, you are declaring bar
into the context of the function foo.
This variable will be available in foo context and all of its "subcontext".
In the first sample, you declare a second function in the foo context so you have access to bar
.
In the second sample, callback is not declared in the foo context. bar
is not accessible for callback, it does not exists.
Upvotes: 0
Reputation: 5258
In the second function, bar is out of scope - it only exists in the function "foo()"; in the function "callback()", bar does not exist and that is why you get the bar is not defined error. I would change it to accept a parameter and print that parameter, like so:
var foo = function (callback) {
var bar = 2;
callback(bar);
}
var callback = function (bar) {
console.log(bar);
}
In this way, callback will print whatever is the passed in value of bar. Another way to do this (depends on your application but could generally be considered less recommended) would be to define bar as a global variable, outside of either function:
var bar = 2;
var foo = function (callback) {
callback();
}
var callback = function () {
console.log(bar);
}
Either way works, but the first method is better encapsulating your code and not making use of a global variable.
EDIT: Here's a less confusing version of the first method, where it's better not to use "bar" variable name in 2 different uses, just for sake of readability:
var foo = function (callback) {
var bar = 2;
callback(bar);
}
var callback = function (myBarParam) {
console.log(myBarParam);
}
Hope this is helpful!
Upvotes: 2
Reputation:
Short answer, just because you call a function from somewhere, it doesn't mean that function has access to everything defined in the scope in which you call it. It has access to everything in the scope where it was defined, though. In the first case, it had access to bar
when it was defined. In the second example, it had not had access to bar
when it was defined, and therefore it complained when you called it.
Long answer: https://developer.mozilla.org/en/JavaScript/Reference/Functions_and_function_scope
Upvotes: 1