0

Consider the following:

function windowTest() { }

(function () {
    function test() { }

    var test1 = new test(); // Works fine.
    var test2 = new window["windowTest"](); // Works since windowsTest is declared globally.
    var test3 = new window["test"]();  // Fails since in an IIFE.

    // How can I create a testObj if I only have the string "test"?
})();

Basically, I want to create an object whose function was declared in an IIFE.

smulz
  • 47
  • 8
  • 1
    Re `test3`: Why do you need to access that function on the `window` object instead of using it directly? – Mike Cluck Jan 27 '17 at 20:33
  • 1
    why does new test() not work? – Jonas Wilms Jan 27 '17 at 20:34
  • test() does indeed work, updated the comment. – smulz Jan 27 '17 at 20:38
  • @MikeC, I'm just looking for a syntax that would get "var test3 = new window["test"]()" to work. Kind of like how "reflection" was used to invoke the object declared globally. But I want to do it in an IIFE. – smulz Jan 27 '17 at 20:39
  • `test` is scoped to the IIFE--since it's not on `window`, no, there's no way to get that to work. You could use `eval`, but yuck. What's the actual problem you're trying to solve? – Dave Newton Jan 27 '17 at 20:43
  • Well, I created my own framework on top of knockoutJS to very easily and dynamically create my huge view models recursively. However, it relies on "new window['constructorName']" to create all of my objects. The idiot that I am, I didn't think global scope would be an issue. Not smart. – smulz Jan 27 '17 at 20:51

2 Answers2

2

The reason

var test3 = new window["test"]();

fails is because test was not declared globally. If you want to access items declared directly within the IIFE, as you know, you can access them by name.

new test();

Another way is to store your function inside of some kind of object then access that object like you did with window. This is almost always the solution to these kinds of problems.

(function() {
  var context = {
    test: function() {
      console.log('new test');
    }
  };
  
  var test = new context['test']();
})();

The last way uses eval. eval is almost always a really bad idea. Really, it should be avoided unless you're abusing the language just for the sake of interest. But you can use it in this case.

(function() {
  function test() {
    console.log('new test');
  }
  
  var test = eval('new test()');
})();
Community
  • 1
  • 1
Mike Cluck
  • 31,869
  • 13
  • 80
  • 91
1

You can bind your functions to this:

function(){
 //your code using
 this.test("Hi");
 this["test"]("Hi");
}.call({
 //function declarations:
 test:window.alert,
});

Still an IIFE so it wont work in the global context :

this.test("Hi");//reference Error
Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151