Beyond My Scope

Today was day one of Javascript. I remember choosing Javascript as the technical track leading up to my interview for Flatiron School. When I got to scope and closures, my comprehension came to a screeching halt. This is exactly where we started today. Thankfully, I found an article on pierrespring.com which explains it nicely.

The example (with slightly modified variable names):

var text = 'Look at me';
var parentFunction = function() {
var childFunction = function() {
var scream = '!!!';
alert(text + ', ' + reason + scream);
}
var reason = "I'm an attention whore";
var scream = '!';
  alert(text + scream);
childFunction();
};
parentFunction();
// 'Look at me!'
// 'Look at me, I'm an attention whore!!!'

At first glance, there’s a lot going on, I’m just not sure what. The indentations elude to some sort of nesting and the output suggests there’s some sort of funny business at hand. My first task was finding a proper definition of scope. MDN to the rescue.

Scope is:

The current context of execution. The context in which values and expressions are “visible,” or can be referenced. If a variable or other expression is not “in the current scope,” then it is unavailable for use. Scopes can also be layered in a hierarchy, so that child scopes have access to parent scopes, but not vice versa.

My first question was, “why assign functions to variables?” I’ve seen multiple ways of defining a function in Javascript, but for simplicity’s sake we’ll stick to the main two, function declarations:

hoisted(); // logs "foo"

function hoisted() {
console.log('foo');
}

And, function expressions:

notHoisted(); // TypeError: notHoisted is not a function

var notHoisted = function() {
console.log('bar');
};

The main thing to note is that function expressions are not hoisted, meaning they cannot be used before they’re defined, and that both parent and child functions in our above example are function expressions. They are only defined when that line is reached.

The next important piece to our puzzle are the variables. This guy hanging out at the top is a global variable. He is defined outside of the function, which automatically makes him global and thus, accessible everywhere in our application.

var text = 'Look at me';

At the very bottom of this nested function is a call to the parent function, which outputs:

parentFunction();
// 'Look at me!'

I was slightly confused. I needed to see the exact contents of each function in isolation. Because the parent does not have access to the scope of its child, the code between the second set of opening and closing curly braces is essentially off-limits. Which leaves these variables available to the parent function call:

var text = 'Look at me';
var parentFunction = function() {
var reason = "I'm an attention whore";
var scream = '!';
  alert(text + scream);
childFunction();
};
// 'Look at me!' 

This now made sense!

And, now the final call to child function summarizes scope perfectly. We grab the global var text = ‘Look at me’, add to it var reason = “I’m an attention whore” which is defined within the parent scope and thus available to the child. The locally scoped var scream takes precedence, resulting in the final output .

Thinking back to my fascination with MDN’s definition of scope, it makes more sense if I can relate it back to real life. Children are dependent on their parents for survival and should have full access to them. Parents are responsible for their children, making it necessary to first ask for permission to access the child.