Adam Halasz
Adam Halasz

Reputation: 58301

This in Private context

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

Answers (1)

Travis J
Travis J

Reputation: 82287

jsFiddle Demo

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

Related Questions