by Andrei Pfeiffer
"Scope" and "Context" in JavaScript are 2 different things. Due to some unfortunate naming conventions by ECMAScript standards and the community itself, there is some confusion about the meaning of these 2 terms.
- Also called "Execution Context" in ECMAScript standards, which explains the confusion between the 2 terms
- Scope is actually a portion of code
- In JavaScript, scope is also named "lexical scope", or "static scope" because it gets evaluated and rendered at compile time
- Scope refers to variables visibility
// global scope var nr = 1; function parent() { // parent scope var nr = 2; function inner() { // inner scope var nr = 3; } inner(); } parent();
- Any variable defined inside of a scope is not visible on the "parent scope" or "outside the function"
- But the same variable is available in all "descendant scopes" or "inner functions"
- So, inner functions contain the scope of the outer functions
- Closures provide the same behavior even after the outer function has returned
- Called "ThisBinding" in the ECMAScript standards
- Can be refered to using "this" keyword
- The "environment" where the function executes
- The context is always an object
- It gets destroyed after it has executed all of the function's code
It's possible to have 2 different functions having the same context
or
It's possible to have 1 function that executes in 2 different contexts
- reserved word, available in all functions
- object (or "undefined")
- points to the function's current context
- takes different values, depending how the function is called
When calling a simple function, it depends if ES5 'strict mode' is enabled or not. If it's enabled, the context will be set to undefined
, otherwise it will reference the window [Object]
, aka. the global object.
function foo() {
console.log( this );
}
foo();
// > global object (window)
function foo() {
'use strict';
console.log( this );
}
foo();
// > undefined
When calling a method from an object, it will always reference the object itself.
var o = {
foo: function() {
console.log( this );
}
};
o.foo();
// > [Object] o
Inside a Constructor, it will always reference the newly created object.
function Foo() {
console.log( this );
}
var o = new Foo();
// > [Object] o (the newly created Object)
To any function, or method, we can pass a custom context, using either call
or apply
methods.
var o = {
foo: function() {
console.log( this );
}
};
var o2 = {};
o.foo.call( o2 );
// > [Object] o2 (the specified Object)
ES5 introduces a new method, that allows permanent binding of a custom context, to a function.
var o = {
foo: function() {
console.log( this );
}
};
var o2 = {};
var bar = o.foo.bind( o2 );
bar();
// > [Object] o2 (the specified Object)