Is there a way to get outer scope variables with t

2020-04-14 01:52发布

问题:

If I defined some variable in outer closure, and in the inner closure has defined another variable with the same name. Can I somehow get the outer variable?

I know it's still somewhere in the memory and not been overwritten since it can be printed after the function. Is there a way to access it?

const foo = 'outer';

function bar() {
  const foo = 'inner';

  // Is there a way to get the outside foo from here?
  console.log(foo);   // "inner", but I want it to be "outer"
}

bar();

console.log(foo); // "outer"

回答1:

If foo is on the top level and declared with const, one of the only ways to access it with new Function, whose scope when run is on the top level. (Please don't actually do this):

const foo = 'outer';

function bar() {
  const foo = 'inner';
  const fn = new Function('return foo');
  console.log(fn('foo'));
}

bar();

console.log(foo); // "outer"

See comment by Hao below. eval can work too, but it's a bit more complicated. As MDN says:

If you use the eval function indirectly, by invoking it via a reference other than eval, as of ECMAScript 5 it works in the global scope rather than the local scope. This means, for instance, that function declarations create global functions, and that the code being evaluated doesn't have access to local variables within the scope where it's being called.

So if you reference eval by any method other than calling the standalone variable name eval(arg), the code will run on the top level, and it will be able to see the variable on the top level:

const foo = 'outer';

function bar() {
  const foo = 'inner';
  console.log(window.eval('foo'));
  // Another method:
  console.log((0, eval)('foo'))
  // Another method:
  const anotherEvalReference = eval;
  console.log(anotherEvalReference('foo'));
}

bar();

console.log(foo); // "outer"

If foo is declared with var instead of const, you can just access that property of the global object:

var foo = 'outer';

function bar() {
  const foo = 'inner';
  console.log(window.foo);
}

bar();

console.log(foo); // "outer"

If the shadowed variable is not on the top level, eg

(() => {
  const foo = 'intermediate';
  (() => {
    const foo = 'inner';
    // more code here
  })();
})();

Then there's no way to access the intermediate variable from the more code here section.



回答2:

I thought I'd add this answer since it might help in some situations.

const foo = 'outer';

function bar() {

  // it's ugly but it works
  {
    const foo = 'inner';
    // rest of your code
  }

  console.log(foo);   // "outer"
}

bar();

console.log(foo); // "outer"