5

The following javascript code, allows you to access the global object (window/worker).

(new function Outer(){
    console.log(this); /* The object */
    (function(){ // This function could be a 3rd Party function 
        console.log(this); /* window !!*/
    })();
});

Is there a way by which I can ensure that the inner this always gets a reference to Outer's context.

I know i can do

(new function Outer(){
    'use strict';
    console.log(this); /* The object */
    (function(){ // This function could be a 3rd Party function 
        console.log(this); /* undefined ? !!*/
    })();
});

but that results in this being undefined.

Edit

I know about bind, but what if the inner function is nested. for instance something like

(function(){

    (function(){
        (function(){
           console.log(this);// undefined
        })();

    })();

}).bind(this)();

What i want is : Outer {} and not a reference to the outer using a variable :-|

ShrekOverflow
  • 6,795
  • 3
  • 37
  • 48
  • 1
    So you don't want `window`, but you also don't want `undefined`. Hate to break it to you, but those are the two defaults that will be used for functions that are invoked without any other indicator of the `this` value. – Blue Skies Nov 25 '13 at 21:29
  • Thats why i asked, wondering if there exists a trick to not have either.. But i guess i will have to be satisfied with `undefined` – ShrekOverflow Nov 25 '13 at 21:33
  • Nope, no trick. I'm not sure what the value would be if it wasn't either of those. ECMAScript 6 will have functions with a lexical `this`, but that's of little use today, and it's only for functions with the new syntax. – Blue Skies Nov 25 '13 at 21:34

3 Answers3

7

You can use function.call.

new function Outer(){
    'use strict';
    console.log(this); 
    (function(){ // This function could be a 3rd Party function 
        console.log(this);  //<-- Now it will it the one from the outer scope
    }).call(this);
}; // You don't need to invoke this explicitly here with () since you are invoking it already with new keyword so constructor invocation doesnt need ()

Or a best bet would be to cache the context outside and use it anywhere in the inner scope.

new function Outer(){
        'use strict';
        var self = this;
        console.log(this); 
        (function(){ // This function could be a 3rd Party function 
            console.log(self);  //<-- Now it will it the one from the outer scope
        })();
 };
PSL
  • 123,204
  • 21
  • 253
  • 243
  • What if the inner function is nested a few level in ? – ShrekOverflow Nov 25 '13 at 21:22
  • 1
    I think you meant `.bind(this)()`, but +1 for doing the right thing. (Also you could use `.call(this)` and have it work *way* back :-) – Sean Vieira Nov 25 '13 at 21:22
  • @AbhishekHingnikar The other solution is to store a reference to the outer `this` inside another variable, like `var that = this` and then use `that` to refer to the outer `this` variable. However, that requires you to edit the code of the inner function. – apsillers Nov 25 '13 at 21:23
  • @SeanVieira yeah i meant call... :) Good catch – PSL Nov 25 '13 at 21:23
  • @SeanVieira or `call` & `apply` for that matter – iConnor Nov 25 '13 at 21:23
  • @AbhishekHingnikar if you have too many of them, then use a cached context. – PSL Nov 25 '13 at 21:26
  • 1
    I know it was from the code in the question, but the final trailing `()` shouldn't be there since the `Outer` function is invoked with `new`. You can also get rid of the wrapping `()`.Just `new function Outer() {...};` is enough. – Blue Skies Nov 25 '13 at 21:31
  • @PSL hmm i can't bind each of them and since the inner function can be 3rd party its a no-luck. – ShrekOverflow Nov 25 '13 at 21:32
  • @BlueSkies yeap my bad... didn't notice that :D removed it – ShrekOverflow Nov 25 '13 at 21:34
  • @AbhishekHingnikar What 3rd party plugin you are using? Does it have a context specification option or something? You cannot do it the traditional way otherwise just by binding it in the outer level – PSL Nov 25 '13 at 21:35
  • I was attempting to write a sandbox for other applications to run freely within mine with some restrictions. – ShrekOverflow Nov 26 '13 at 10:04
1

You can use a closure variable:

(new function Outer(){
    'use strict';
    console.log(this);
    var me = this;
    (function(){
        console.log(me);
    })();
})();
seand
  • 468
  • 6
  • 23
1

This trick simply stores the "outer" this inside a variable that you can access from inner functions (and inner-inner function and so on).

In some cases, this can be useful because you have access to both the inner this (if there is a context for it) and the outer this.

(new function Outer(){
    'use strict';
    console.log(this); /* The object */
    var _this = this;
    (function(){ // This function could be a 3rd Party function 
        console.log(_this); /* The outer object */
    })();
})();
Fenton
  • 241,084
  • 71
  • 387
  • 401