is it evil to use eval to convert a string to a function? [closed]

I have heard lot's of different opinions on eval() and are a bit unsure if it's ok to use eval() in this context:

let's say I have an object like this:

var bla = {
blubb: function (callback) {
       //GET some stuff via ajax
       //call the callback
    }
}

And a string like this:

 var someString = "bla.blubb";

Is it evil to eval the string in order to call the function (and the callback)?

var callMe = eval(someString)
callMe(function(){
   alert('yay')!
});

Answers:

Answer

i have heard lot's of different opinions on eval()

eval is not evil in general, there are applications for it.

unsure if it's ok to use eval() in this context

No, it is not OK for this. There is a much better solution using the simple bracket notation member operator. Since this is asked every day on SO, I can list hundreds of dupes here (just the first few Google results):

Answer

Let's suppose your whole design isn't totally evil (but a little).

That would mean you restrict and specify what you have in someString. For example it could be the path to an object and its function that you would call without any argument (which makes it much less dangerous) and with context the global object.

Then it's easy to parse the string and call the function without eval. This would be more secure. For example :

window.a = {b:{c:function(){console.log('here')}}};
var someString = "a.b.c";

var path = someString.split('.');
var f = window;
for (var i=0; i<path.length; i++) f = f[path[i]];
f.call(null);

An improvement would be to fix a root object (and not window) to avoid any kind of call.

Answer

Dont forget you can use a "safe eval" in javascript if you know what your objects will look like.

inside a scope :

this.foo = { bar:function(){return "baz"}};

// some code.
var obj = "foo";
var param = "bar";

this[obj][param](); // same as this.foo.bar();

Unless you are dealing with some specific things (like templating for instance) ,you should not need to use eval to call objects.

Answer

It's evil again because it's hard for debugging. Better approach is to use something like:

function getValue(namespace, parent) {
    var parts = namespace.split('.'),
        current = parent || window;
    for (var i = 0; i < parts.length; i += 1) {
        if (current[parts[i]]) {
            current = current[parts[i]];
        } else {
          if (i >= parts.length - 1)
            return undefined;
        }
    }
    return current;
}
var foo = {
    bar: {
        baz: function () { alert('baz'); }
    }
};
var f = getValue('foo.bar.baz'); //true
if (typeof f === 'function') {
    f();
}

The code is more than a single eval('foo.bar.baz') but you can figure out what's actually happening and even debug it with break points.

If we speak about performance here are few jsperf examples:

  1. http://jsperf.com/eval-vs-loop
  2. http://jsperf.com/eval-vs-loop/2

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.