2

Is there a way to reference the next object up the scope chain in Javascript?

So, for example:

var a = 12;
function run() {
  var a = 34;
  alert( a ); //replace "a" with something like "parent.a" so it shows 12 instead of 34
}
run();
cambraca
  • 27,014
  • 16
  • 68
  • 99
  • 1
    as far as i know, its impossible. – c69 Jul 17 '12 at 22:38
  • Sounds like a recipe for confusion it it were possible. – Lee Taylor Jul 17 '12 at 22:43
  • @LeeTaylor no doubt, I just want to know if it's possible. Kids, don't do this at home! – cambraca Jul 17 '12 at 22:43
  • It's impossible for the example you postet. If you used inheritance you could use super to get the a that is 12. – bastianwegge Jul 17 '12 at 22:44
  • This impossibility is also a bonus for security, as it allows completely hiding what is behinf the blackbox of the closure. The closure mechanims is very strict. It's good but it may also have caveats as it becomes impossible to know if an environment is safe or if it was not hacked by a malware spying and hooking what your site does. – verdy_p Jul 17 '12 at 22:53

6 Answers6

3

Nope, there is not. Javascript doesn't expose the scope chain at all really (much to my chagrin; I'd love to be able to write a function that adds variables to the local scope, but alas I can't).

machineghost
  • 33,529
  • 30
  • 159
  • 234
  • Preventing access to the lexical environment means that you can't use it as a data store and that you must use an object to store data, which (for javascript) is nearly always a better solution. – RobG Jul 18 '12 at 02:06
1

The short answer is no. JS have closures that lets you "save" the scope state, but that's not the same. You can read about that here: How do JavaScript closures work?

Community
  • 1
  • 1
valentinas
  • 4,277
  • 1
  • 20
  • 27
  • I'm not trying to do anything practical with this. Just curious about JS. – cambraca Jul 17 '12 at 22:44
  • I see. You might find this interesting: http://stackoverflow.com/questions/111102/how-do-javascript-closures-work but yeah, changing scope, accessing parents is not possible in JS.. – valentinas Jul 17 '12 at 22:47
0

You could use this trick, assigning the inner a variable as a pseudo static property to the run function:

var a = 12;
function run() {
  run.a = 34; //or arguments.callee.a = 34
  alert( a );
}
run(); //=> 12

If the first a is a global variable in the browser, this is also a possibility:

var a = 12;
function run() {
  var a = 34; //or arguments.callee.a = 34
  alert( window.a ); //global variables are a property of window
}
run(); //=> 12
KooiInc
  • 119,216
  • 31
  • 141
  • 177
0

Other answers are correct, but you should know that ECMA-262 explicitly states that the "scope" object (i.e. lexical environment) can't be referenced or modified directly by script. The only exception is that global variables are made properties of the global (synonymous with window in a browser) object.

Lexical Environments and Environment Record values are purely specification mechanisms and need not correspond to any specific artefact of an ECMAScript implementation. It is impossible for an ECMAScript program to directly access or manipulate such values.

ECMA5 §10.2

RobG
  • 142,382
  • 31
  • 172
  • 209
0

Maybe it helps, at least you can insert a backdoor to the inner scope of a context:

function Foo() {
    var a = 123; // much private
    this.b = 456; // much public
    this.eval = function(code) { return eval(code) } // backdoor to inner scope
}
foo = new Foo()
console.log("foo.eval(\"a\": ", foo.eval("a")) // 123
console.log("foo.eval(\"b\": ", foo.eval("b")) // ReferenceError: b is not defined
console.log("foo.eval(\"this.b\": ", foo.eval("this.b")) // 456
console.log("foo.a:", foo.a) // undefined
console.log("foo.b", foo.b) // 456
kungfooman
  • 4,473
  • 1
  • 44
  • 33
0

I think the solution you are looking out for is:

var a = 12;
function run() {

   var a = 34;
   alert(window.a); 

  /*accesses the global window object to which any variable 
      in the global scope gets binded*/
}
run();
Rahul Arora
  • 4,503
  • 1
  • 16
  • 24