4

Consider the following code:

(function() {
    var a = 5;
    var someFunc = function() { ... };
    function anotherFunc() {
        ...
    };
})();

window.myGlobalObj = {
    init: function() {
        // and somehow here I want to  access to the IIFE context
    }
};

I want to have the execution context of IIFE in my global object. I do have access to function expression and object itself so I can pass or modify something to make it work (and no, I can't rewrite everything inside the object or function).

Is it even possible?

Ilya Tsuryev
  • 2,766
  • 6
  • 25
  • 29

3 Answers3

2

The "contents" of your IIFE, i.e., a, someFunc, etc., are local to that function scope, so you can only access them within that scope. But you can assign window.myGlobalObj inside the IIFE:

(function() {
    var a = 5;
    var someFunc = function() { ... };
    function anotherFunc() {
        ...
    };

    window.myGlobalObj = {
        init: function() {
           // and somehow here I want to  access to the IIFE context
        }
    };

})();

Then the init function will have access to those variables since they are in its containing scope.

EDIT: if you can't move the definition of myGlobalObj into the IIFE the only thing I can think of is to use the IIFE to create a second global object that you access from myGlobalObj:

(function() {
    var a = 5;
    var someFunc = function() { ... };
    function anotherFunc() {
        ...
    };

    // create a global object that reveals only the parts that you want
    // to be public
    window.mySecondObject = {
       someFunc : someFunc,
       anotherFunc : anotherFunc
    };
})();

window.myGlobalObj = {
    init: function() {
        window.mySecondObject.someFunc();
    }
};
nnnnnn
  • 147,572
  • 30
  • 200
  • 241
2

The only way I see how that's poosible is by using eval to simulate dynamic scopes. Do this (note that the IIFE must be placed after the global object):

window.myGlobalObj = {
    init: function() {
        // and somehow here I want to  access to the IIFE context
    }
};

(function() {
    var a = 5;
    var someFunc = function() { ... };
    function anotherFunc() {
        ...
    };

    eval("(" + String(window.myGlobalObj.init) + ")").call(window.myGlobalObj);
})();

Here's a reference as on how to use dynamic scopes: Is it possible to achieve dynamic scoping in JavaScript without resorting to eval?

Edit: I've included an example to demonstrate the power of using dynamic scopes in JavaScript. You can play with the fiddle too.

var o = {
    init: function () {
        alert(a + b === this.x); // alerts true
    },
    x: 5
};

(function () {
    var a = 2;
    var b = 3;

    eval("(" + String(o.init) + ")").call(o);
}());
Community
  • 1
  • 1
Aadit M Shah
  • 72,912
  • 30
  • 168
  • 299
  • While I won't actually actually use such scheme in application but that was very interesting, learned something new! – Ilya Tsuryev Apr 23 '12 at 11:44
  • Glad to help. There are lots of hacks one can exploit if you're willing to learn more about `eval` and how it can be used safely. For example you can implement [pointers](http://hpyblg.wordpress.com/2010/05/31/simulating-pointers-in-javascript-part-2/ "Simulating pointers in JavaScript, part 2 « Happy Blog, the Happy Blog") in JavaScript using `eval`. – Aadit M Shah Apr 23 '12 at 11:51
  • @Stonerain, you've just learned pretty nasty thing. Avoid it! Eval is frowned upon by masters like Douglas Crockford. The code is ugly, hard to understand and debug, inefficient and poses other dangers. Using it for this purpose is abuse. – Tomas Apr 24 '12 at 07:05
  • 1
    @Tomas, I think that's a bit too harsh. The function `eval` itself is not frowned upon by Douglas Crockford. It's the improper use of the function by amateur programmers which causes problems. Most of the use cases of `eval` may be accomplished without it. However there are still some use cases which genuinely require `eval`. If used properly `eval` is a safe tool. I said this before and I'll say it again - most of the [fear](http://www.asiantravelhotel.com/javascript/when-is-javascript-39-s-eval-not-evil.html) regarding `eval` is just because of ignorance. Don't blame `eval` for bad programs. – Aadit M Shah Apr 24 '12 at 11:01
  • @Aadit, thanks for the [link you posted](http://www.asiantravelhotel.com/javascript/when-is-javascript-39-s-eval-not-evil.html). I can only agree with this: *"All such unnecessary uses of eval add to a maintenance hell. Refactoring tools are thrown off. Searching for code is hard. Unanticipated effects of those evals are legion."* – Tomas Apr 24 '12 at 11:22
  • And this: *"While there may be numerous instances where you can accomplish what you need to accomplish by concatenating a script together and running it on the fly, you typically have much more powerful and maintainable techniques at your disposal: ... closures, object-oriented techniques, functional techniques - use them instead."* So, @Stonerain, think twice before you introduce ev*l to your code. – Tomas Apr 24 '12 at 11:22
  • @Tomas, that's one perspective, but it's not the entire picture. I would love to discover a solution to the OP's problem using closures, object-oriented techniques, or functional techniques. Like I said before, oblige me if you can provide a solution. On the other hand using `eval` properly (as is the above case) wouldn't lead to unanticipated effects (since the evaluated code is executed in a separate functional scope); and refactoring or searching for line numbers won't be a problem. All you need to do is replace the line with `eval` with the actual function body and then debug. Automatable. – Aadit M Shah Apr 24 '12 at 11:38
  • *"I would love to discover a solution to the OP's problem using ..."* - just look at the @nnn's answer or mine. *"All you need is to replace ..."* but why such complications? Anyway, won't argue any more. – Tomas Apr 24 '12 at 12:49
0

No. It is not possible. The context you want to access is called closure and can be accessed only within the function (in your case, the anonymous function (IIFE how you call it)). For more about closures follow the excellent Douglas Crockfords The Javascript programming language video tutorial.

You will have to place those attributes to some shared object.

Tomas
  • 57,621
  • 49
  • 238
  • 373
  • Actually it is possible. All you need to do is simulate dynamic scopes in JavaScript using `eval`. I know that `eval` is considered evil but there are cases where it's necessary. Even jQuery uses `eval`. Simulating dynamic scopes in JavaScript is one of those cases in which it's actually safe to use `eval`. You can read more about it from here: [Is it possible to achieve dynamic scoping in JavaScript without resorting to eval?](http://stackoverflow.com/q/10060857/783743 "Is it possible to achieve dynamic scoping in JavaScript without resorting to eval?") – Aadit M Shah Apr 23 '12 at 11:25
  • @AaditMShah, this would really gone to be a bad practice! I'd call it a dirty hack and ban it. BTW, usage of eval within jQuery for JSON parsing is considered a big weakness and jQuery is criticized for that. That's why it is best to use [Douglas Crockford's json2.js](http://json.org/) for that purpose. – Tomas Apr 23 '12 at 11:31
  • With your answer you practically showed I was right - it is not possible (*within reasonably sane code*). – Tomas Apr 23 '12 at 11:37
  • 2
    It is not really a bad practice. There's a lot of fear amongst programmers when it comes to `eval` and most of it is because programmers don't really know how it is harmful. However in the right hands it's a safe and powerful tool. Think about it - if it's really so bad then why not remove it from the language altogether? It's still there in EC5. Using `eval` to simulate dynamic scopes is one of those cases in which `eval` is not evil. It's not possible to break existing code in this use case - unless the programmer deliberately messes things up which in all probability will never be. – Aadit M Shah Apr 23 '12 at 11:39
  • I'm sorry. How exactly is my code going to do any harm? If you can prove it to me within reasonable bounds that there's a better way to tackle this problem without using `eval` then please do oblige me. I don't see how using `eval` in this case could lead to unsafe code. Don't just tell me that I'm wrong. Show me with a test case. – Aadit M Shah Apr 23 '12 at 11:43