What are free variables?
Free variables are simply the variables that are neither locally declared nor passed as parameter.
Source :
In computer programming, the term free variable refers to variables used in a function that are not local variables nor parameters of that function.1 The term non-local variable is often a synonym in this context.
In javascript closures, those are simply the variables that the function takes (read and write) in the enclosing scope where is declared the closure or in a parent scope.
Look at this real world example :
Gol.prototype._ensureInit = function() {
...
var _this = this;
var setDim = function() {
_this.w = _this.canvas.clientWidth;
_this.h = _this.canvas.clientHeight;
_this.canvas.width = _this.w;
_this.canvas.height = _this.h;
_this.dimChanged = true;
_this.draw();
};
setDim();
window.addEventListener('resize', setDim);
...
};
In this example a closure points from the setDim
function towards the variable _this
declared in the enclosing scope (the _ensureInit
function). This variable isn't declared in setDim
nor passed. It's a "free variable".
Note that _this
doesn't become a variable of the function setDim
: another function declared in the same scope would share the same variable.
As an example:
var myModule = (function (){
var moduleVar; // closure variable
return function(){
// actual function
}
})();
the variable defined there is a closure variable. it can be used all over the closure itself but is not part of a global namespace.
A "free-translation" could be: "out of scope" - variables
.
Since ECMAscript uses lexical scoping, a free variable is a variable which was defined in a parent-scope and gets looked-up by a scope-chain search.
(function _outerScope() {
var foo = 42;
(function _innerScope() {
var bar = 100;
console.log( foo + bar ); // 142
}());
}());
In the above example, foo
is a free variable within the context of _innerScope
. it becomes very obvious if we have a quick glance into the underlying concepts of ECMAscript.
A Context is linked to an Activation Object (in ES3), respectively a Lexical Enviroment Record (in ES5), which contains things like: function declarations
, variables declared with var
and formal paramters
, as well as a reference to all parent Activation Objects / Lexical Environments. If a variable needs to be accessed, the ECMAscript engine will first look into the AOs / LEs from the current Context itself; if it can't be found there, it looks into the parent AO's / LE's.
Since any Context stores this data in an array-like structure (don't forget we're talking about implementation level here, not Javascript itself), we are talking about Lexical Scope
, because we search through all parent Contexts in order.