Saturday, February 23, 2019

5.7 Closures

The bind function takes advantage of something in JavaScript known as a closure. This takes advantage of the way that scope works within JavaScript and can be used to hide variables within a function. For binding it is making sure that the reference to the object that created the object is tracked.

Scope simply is a term that describes which variables are known to a particular piece of code. The visibility of a variable depends on where it is declared. When declared outside of a function it is global and is visible to everything, including other scripts running on the same web page, which is why you do not want to have global variables in your code if you can help it. Variables declared within a function are only visible to code within that function. Variables declared within a loop are only visible to code within that loop, and so on. The code within the loop, however, can see all the variables in the scopes leading up to it.

The purpose of scope is two-fold. First, each layer of scope can be considered it's own name-space. Second, and more importantly, this allows JavaScript to know which variables are no longer needed and can be garbage collected so that the memory it used can be reclaimed for use by other things. There is an exception to this garbage collection rule, any variable that is still being referenced by another variable that is still in scope will not be garbage collected.

Functions within another function have access to the parent function's variables. This information is stored in a scope chain, the details of which are a bit beyond the scope of this chapter but the nutshell is that the function has access to the information contained within the function that created. This means that if we have a case where there is a reference to the inside function then even if the outside function goes out of scope, the outside functions data will not be garbage collected as it is still referenced by something that is still in-scope.

Here is a simple demonstration:

// General function for printing to the web page so results can be seen// without requiring the console
function printTestLine(s) {
// we are grabbing an html element
var results = document.getElementById("testResults");
// now append the new line to this element
results.innerHTML = results.innerHTML + "
" + s

}

function HiddingVariables(p, v) {
this.publicValue = p;
var hiddenValue = v;

this.getHiddenValue = function() {
return hiddenValue;
}

this.bindPrint = function() {
var owner = this;
return function() {
printTestLine("The hidden value is " + owner.getHiddenValue());
}
}
}

var hiddenVar = new HiddingVariables(21, 42);
printTestLine("Attempting to read public variable: " + hiddenVar.publicValue);
printTestLine("Attempting to read hidden variable: " + hiddenVar.hiddenValue);
printTestLine("Getting through method: " + hiddenVar.getHiddenValue());
setTimeout(hiddenVar.bindPrint(), 1000);

When the HiddingVariables function runs, the public value is stored as part of the object. The hidden variable is a local variable which means that it will go out of scope as soon as the function finishes running. As the function has a reference to this value, it is still visible to it. If you still don't quite understand how a closure works, don't worry too much as it is not necessary to understand them to use them.

Now that we have a basic understanding of classes we use some of these concepts in the next chapter when we create the Nightmare Maze game.

No comments: