var value = 10;
var outer_funct = function(){
var value = 20;
var inner_funct = function(){
var value = 30;
console.log(value); // logs 30
var value = 30;
is a local variable in function outer_funct
, it could not be accessed from outside of this function.
in your code, although winodw["outer_funct"]["value"]
is written inside inner_funct
but it acts as trying to access a local variable from out of outer_funct
because by `window['outer_funct'] you are staying at the top level.
You cannot refer to value
using window["outer_funct"]
exactly for the reasons you mentioned. What you can do is something like this:
var value = 10;
var outer_funct = function(){
var context = {// you can put multiple values in here
value: 20;
}
var inner_funct = function(){
var value = 30;
console.log(value); // logs 30
console.log(context.value); //logs 20
console.log(window["value"]); // logs 10
};
inner_funct();
};
outer_funct();
Another way you can do it is if you haven't shadowed value
inside inner_funct
. If you don't have a variable named the same thing, you can log it and it will return 20
. But since you created another variable named value
inside inner_funct
, that will shadow the value of value
in outer_funct
.
I would also question why you would need to have three variables named exactly the same, across three scopes.
I believe the reason the second log is returning undefined is because window["outer_funct"] refers to the function object, and the function object doesn't have a property "value" associated with it.
Correct.
Instead, what I would like to do is refer to the execution context when window["outer_funct"] is invoked. Is this possible to do within the execution context of inner_funct?
No, not with you having shadowed value
(declared it in inner_funct
). You have no way of getting to it with that symbol having been overridden like that. You could, of course, grab it into another symbol:
var value = 10;
var outer_funct = function(){
var value = 20;
var outer_value = value;
var inner_funct = function(){
var value = 30;
console.log(value); // logs 30
console.log(outer_value); // logs 20
console.log(window.value); // logs 10
};
inner_funct();
};
outer_funct();
If you hadn't shadowed it, then you could refer to value
in the containing context, e.g.:
var value1 = 10;
var outer_funct = function(){
var value2 = 20;
var inner_funct = function(){
var value3 = 30;
console.log(value3); // logs 30
console.log(value2); // logs 20
console.log(value1); // logs 10
};
inner_funct();
};
outer_funct();
It's worth noting that the only reason that your original code's window["value"]
returned 10
(btw, you could also use window.value
) is that the var value = 10;
is at global scope. All variables declared with var
become properties of the global object, which on browsers is referred to via window
(technically, window
is, itself, just a property on the global object that points back to the global object).
Variables don't become properties of the functions under which you define them. Excluding the window
object (in the case where they are globally declared) there's no object off of which you can access a locally-defined variable. There are workarounds as suggested by the other answers, but they are still a testament to JavaScript's inability to perform such a task in the actual circumstance that you've shown us.
No, it is absolutely impossible to access non-global shadowed variables in JavaScript.
You cannot get the execution context of a function as well, it is an implementation-dependent internal value (specification type) - you are correct, your code was looking for properties on the function object.
Variables in the global scope could be accessed as properties of the global object (window
in browser), but if you are shadowing a local variable your only choice is to rename your own variable that casts the shadow.
Local variables are intended to be non-accessible, also because they can depend on the function execution (how could you access that variable if the function has never been executed?).
If you really need some trick, you can have a look at this:
var person = function () {
// Private
var name = "Robert";
return {
getName : function () {
return name;
},
setName : function (newName) {
name = newName;
}
};
}();
alert(person.name); // Undefined
alert(person.getName()); // "Robert"
person.setName("Robert Nyman");
alert(person.getName()); // "Robert Nyman"
and notice that the function must be executed before you can use accessible methods.