Reputation: 58301
I would like to access variables created inside a private context. I'm creating a private context like this:
(new Function("var a = 'hello'; console.log('this', this);")).call({});
// outputs -> this Object {}
I'm call
'ing the function with an empty context. But this
doesn't holds the a
variable. And anyway how is it possible that console.log
works with an empty context?
Upvotes: 1
Views: 170
Reputation: 82287
Inside of the scope for the function which creates the object var a
is present. However, once that scope is lost, so is the variable. If you would like a
to persist, you would need to attach it to the object that is created using the this
keyword:
(new Function("this.a = 'hello'; console.log(this);")).call({});
However, this is an obfuscated way of doing it. There are elements which are not required here. Mainly that the new
keyword is not needed (Function
implies a function object). Function
also comes with methods, such as call
.
Function("this.a = 'hello'; console.log(this);").call({});
This will also work. Moreover, if you would like to retain what is in the variable a, you could always do this (demo):
var obj = {};
Function("this.a = 'hello'").call(obj);
obj.a;//hello
As for why it works with an empty context. You have actually given it a freshly constructed object with {}
. So that is the scope that is used inside of the function when the reference this
is encountered. In fact, call()
does not need arguments if you are not intending to use scope. Something like this:
Function("console.log(5);").call();
will log 5
to the console without error.
The approach used in your question is to build a function from a magic string. That approach is pretty cool I must say, very similar to eval. But what you are looking for boils down to this difference I think:
function ball(){
var color = "red";
return color;
}
function Ball(){
this.color = "red";
}
console.log(ball());//logs red
console.log(new Ball().color);//logs red
Upvotes: 2