antonjs
antonjs

Reputation: 14318

Function context using callback

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

Answers (6)

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

Eugen Rieck
Eugen Rieck

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

JaredPar
JaredPar

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

dievardump
dievardump

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. baris not accessible for callback, it does not exists.

Upvotes: 0

Dmitriy Khaykin
Dmitriy Khaykin

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

user234932
user234932

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

Related Questions