kingbot
kingbot

Reputation: 23

Callback/scope understanding

So i was playing around with the concept of callbacks and i ran into a situation where I wanted to make sure i knew what i thought was happening, was actually happening.

function greet(callback) { // 'greet' function takes a callback
  var greeting = "hi";     // 'greeting' variable is set in the scope
  callback()               // 'callback' function is invoked 
}

greet(
function() {
  console.log(greeting)
}); 

//Console logs nothing

Sorta weird, you'd expect the callback() to look in its next closest scope and figure out what greeting is. However, once i declare the greeting variable to the global execution context, greeting is logged in the console.

var greeting = 'hi'        // 'greeting' variable is set in global context

function greet(callback) { // 'greet' function takes a callback    
  callback()               // 'callback' function is invoked 
}

greet(
function() {
  console.log(greeting)
}); 

//Console logs: 'hi'

Is this because technically the callback() function that's logging the variable is actually defined in the global context and is simply being invoked inside of greet()? So it's not going to look inside of greet() first, like a normal function expression would, but right into the global context because that's where it's defined.

I just wanted to make sure i understand what's happening here and not some weird scope/block issue that i don't realize.

Upvotes: 2

Views: 2410

Answers (3)

EyuelDK
EyuelDK

Reputation: 3199

Javascript uses Static Scoping

TLDR; Variables are resolved according to their location in the source code.

greeting is only defined with the closure of the greet function. Only code defined within the greet function closure can see the greeting variable.

function greet(callback) { // 'greet' function takes a callback
  var greeting = "hi";     // 'greeting' variable is set in the scope
  callback()               // 'callback' function is invoked 
}

greet(function() {
  console.log(greeting)
}); 

Here though, greeting is defined in a scope accessible by the nested closures of the greet function and the anonymous function used in the console.log call.

var greeting = 'hi'        // 'greeting' variable is set in global context

function greet(callback) { // 'greet' function takes a callback    
  callback()               // 'callback' function is invoked 
}

greet(function() {
  console.log(greeting)
});

NOTE: this keyword has a different set of rules.

Upvotes: 0

James Monger
James Monger

Reputation: 10685

You're right - the function has access to the scope which it is defined in.

Your example is effectively this (moving your callback to its own function):

var greeting = 'hi';

function greet(callback) {
    callback();
}

function logGreeting() {
    console.log(greeting);
}

greet(logGreeting);

As you can see, logGreeting has access to greeting at this point because it is defined in the same (or higher) scope.

However, when we move greeting into the greet function:

function greet(callback) {
    var greeting = 'hi';
    callback();
}

function logGreeting() {
    console.log(greeting);
}

greet(logGreeting);

greeting is no longer in the same or higher scope to logGreeting, it's in a different scope entirely, so logGreeting cannot look upwards through the scope in order to find greeting.

The scope which logGreeting has access to is the scope in which it is defined rather than which it is called, so it doesn't evaluate the scope when it's called with callback() like you mentioned in your question.

Upvotes: 2

aaronjkrause
aaronjkrause

Reputation: 849

That's an example of lexical scope which is how JavaScript handles scope, as opposed to dynamic scope. In a nutshell lexical scope determines the context based on where things are defined and dynamic is based on where it's called.

For your first example to work like you thought would be dynamic scope.

You can read a bit more detail here in the "Lexical scope vs. dynamic scope" section.

https://en.wikipedia.org/wiki/Scope_(computer_science)

Upvotes: 2

Related Questions