En la creación de una función se define su propiedad (interna) Scope que es la lista jerárquica de todos los Objetos Variable de sus “padres” (que estan por encima de su contexto)
En la llamada a una función se crea el Scope Chain (cadena de ámbitos) del contexto de ejecución que es: su Objeto de Activación + la propiedad Scope de esta función
La resolución de identificadores ( Identifier Resolution ) es el proceso en el cual se determina a qué Objeto Variable dentro de la cadena de ámbitos pertenece una variable determinada
var x = 10;
function foo() {
var y = 20;
function bar() { alert(x + y); }
return bar;
}
foo()(); // 30
Al llamar a la función su Contexto de Ejecución queda asi…
activeExecutionContext = {
VO: {...}, // or AO
this: thisValue,
Scope: [ // Scope chain
// list of all variable objects
// for identifiers lookup
]
};
donde su Scope seria…
Scope = AO + [[Scope]]
es decir…
Scope = AO + [VO1, VO2, ..., VOn]
donde…
var VO1 = {__parent__: null, ... other data}; -->
var VO2 = {__parent__: VO1, ... other data}; -->
// etc.
More info:
var x = 10;
function foo() {
var y = 20;
function bar() {
var z = 30;
alert(x + y + z);
}
bar();
}
foo(); // 60
Partimos del objeto global ya creado, que además es la Variable Objeto del Contexto Global…
globalContext.VO === Global = {
x: 10
foo: <reference to function>
};
En la creación de “foo”, la propiedad "Scope" de “foo” es…
foo.[[Scope]] = [
globalContext.VO
];
En la activación de “foo” (al llamar a la función, al entrar en su contexto) , el objeto de activación del contexto “foo” es…
fooContext.AO = {
y: 20,
bar: <reference to function>
};
Y el Scope Chain del contexto “foo” queda…
fooContext.Scope = fooContext.AO + foo.[[Scope]] // i.e.:
fooContext.Scope = [
fooContext.AO,
globalContext.VO
];
En la creación de la función interna “bar” su Scope es…
bar.[[Scope]] = [
fooContext.AO,
globalContext.VO
];
En la activación de “bar”, el objeto de activación del contexto “bar” es…
barContext.AO = {
z: 30
};
Y el Scope Chain de “bar” queda…
barContext.Scope = barContext.AO + bar.[[Scope]] // i.e.:
barContext.Scope = [
barContext.AO,
fooContext.AO,
globalContext.VO
];
Asi, la resolución de identificadores para “x”, “y” y “z” se haría asi…
- "x"
-- barContext.AO // not found
-- fooContext.AO // not found
-- globalContext.VO // found - 10
- "y"
-- barContext.AO // not found
-- fooContext.AO // found - 20
- "z"
-- barContext.AO // found – 30