Snowman
Snowman

Reputation: 2495

Executable code from object (preferably without eval())

I have this code to execute in a backbone project:

main.key1 = new view.a.b.c({prop: val});
main.key2 = new view.x.y.z({prop: val});
//and so on, about 10 views with about 5 identical properties

I have an object like this defined inside a main object:

var main = this;    
var viewmap = {key1: 'view.a.b.c', key2: 'view.x.y.z'} // and so on

What I want is to use my object to replace the code above, because the views have to come from a map.

I'm not 100% against eval(), but I'd prefer not to have to use it. However, if that is the only way, I'll take it. Problem is, I'm not even sure how to use eval() for this purpose.

I tried something like:

for(view in viewmap){
    main[view] = eval('new ' + viewmap[view] + '({prop: val});');
}

But it's not working.

Please help.

Upvotes: 0

Views: 66

Answers (1)

Paul S.
Paul S.

Reputation: 66364

Splitting the string at .s then looping over the resulting array and using bracket notation to find the next object, you'd end up with code that looks something like this

function getObj(base, path) {
    var arr = path.split('.'), // ["view", "a", "b", "c"]
        i;
    for (i = 1; i < arr.length; ++i) // start from 1 to ignore "view"
        if (!(base = base[arr[i]]))
            break; // error handling?
    return base;
}
// now your loop that uses `new` on the result of the invocation of the function
var viewPath;
for(viewPath in viewmap){
    main[viewPath] = new (getObj(view, viewmap[viewPath]))({prop: val});
}

Notice the extra pair of parenthesis around the getObj call so the interpreter doesn't confuse this with the new

Upvotes: 1

Related Questions