2

I have a constructor function, for example webapp.core.cf1 or Backbone.Router. But I get this constructor function not as a reference, but as a string! I cannot change this requirement, the constr. must be in a string. How can I make a new object from this, for instance classfun("Backbone.Router")?

function classfun (cfstr) 
{ 
  ...
  cf = new window[cfstr]();

If I try it this way, I get the error: ... is not a constructor.

Why this does not work? Is there an alternative way without using eval()?

Thanks a lot in advance

EDIT

Thank you all for your answers!

Thank you, Tronix117, this was the problem!!

Thank you, Benjamin Schulte, for the function!

3
  • Can you give a complete example? Perhaps, on jsfiddle.net? Commented Apr 19, 2012 at 12:49
  • and also, sample code of what you really want to happen? Commented Apr 19, 2012 at 12:50
  • How do you call classfun? What type of variable are you passing into it? Commented Apr 19, 2012 at 12:51

3 Answers 3

5

If you try in your console:

var A=function(a){this.test=a};
b = new window["A"](3);
console.log(b.test); // return 3

So that means, you are trying to access something which is not in the scope of window, it should rather be something like that: window.something["A"], if you don't know what is something then you should use the function of Benjamin, otherwise use this one, because it's way faster.

Sign up to request clarification or add additional context in comments.

3 Comments

Good stuff checking the window object for the property of the classname. This solved an issue I was having. Thanks!
Not that his question asked this, but what about in non-browser js?
@catbadger there is always a top level object, it's usualy global in non-browsers environments like node.js and window in browser environments. If you want to be cross-env (brower + non browser), you can do this: typeof global === 'undefined' && (window.global = window) at the beginning of the script, and use global everywhere you need. So in the above exemple you then do b= new global['a'](3).
3

You can do it this way (if I understand you correctly):

function getObjectByName(name) {
    var nameParts = name.split('.');
    var nameLength = nameParts.length;
    var scope = window;

    for (var i=0; i<nameLength; ++i) {
        scope = scope[nameParts[i]];
    }

    return scope;
}

var ObjectClass = getObjectByName(cfstr)
new ObjectClass();

Can still be optimized, but should work this way.

Comments

1
ReflectUtil.newInstance = function(strClass) {
    var args = Array.prototype.slice.call(arguments, 1);
    var clsClass = eval(strClass);
    function F() {
        return clsClass.apply(this, args);
    }
    F.prototype = clsClass.prototype;
    return new F();
};

SomeClass = function(arg1, arg2) {
    // ...
}

ReflectUtil.newInstance('SomeClass', 5, 7);

This will allow you to instantiate an object by its name and allow you to pass parameters as necessary.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.