6

From PHP development I know that eval is evil and I've recently read What constitutes “Proper use” of the javascript Eval feature? and Don't be eval. The only proper use of eval I've read is Ajax.

I'm currently developing a visualization tool that lets users see how polynomials can interpolate functions:

enter image description here

I use eval for evaluation of arbitrary functions. Is this a legitimate use of eval? How could I get rid of eval?

I want the user to be able to execute any function of the following forms:

  1. a x^i with a,i in R
  2. sin, cos, tan
  3. b^x with b in R
  4. any combination that you can get by
    • adding (e.g. x^2 + x^3 + sin(x)),
    • multiplying (e.g. sin(x)*x^2) or
    • inserting (e.g. sin(x^2))
8
  • 1
    You might use a math library on it, for example: mathjs.org which takes care of parsing. Jul 1, 2013 at 8:54
  • 7
    "Eval is evil" is just the same degree of ignorance as the classic stupid rant "goto is evil". Eval is a legitimate and powerful tool for runtime metaprogramming.
    – SK-logic
    Jul 1, 2013 at 9:09
  • 1
    @SK-logic but you need to tread lightly, and there's normally a better way. Jul 1, 2013 at 9:11
  • @JanDvorak, metaprogramming is nearly always a better way than anything else. With languages like JavaScript there is no distinction between compile-time and runtime metaprogramming, therefore eval is a legitimate way of doing nearly everything (in absence of proper macros).
    – SK-logic
    Jul 1, 2013 at 9:13
  • @SK-logic Metaprogramming is good if it's what you want. And when you want metaprogramming, there's more tools for metaprogramming than eval. eval is without a doubt the most powerful, but it's also more brittle and dangerous than more specialized tools. For example, there is no reason to use eval for getting an attribute dynamically, as in eval('obj.'+attrname) - that's what obj[attrname] is for.
    – user7043
    Jul 1, 2013 at 9:23

3 Answers 3

8

I see nothing not "legitimate", eval isn't evil per se and it has been precisely designed to evaluate arbitrary code. It lets you here make a fast, complete expression evaluator without resorting to complex libraries and it gives your user the power of JavaScript.

But right now you're evaluating the input for each x. This is very slow.

I would do this so that it can be used more efficiently :

var f = Function('x','return '+input);

When input is Math.sin(x), this builds a function you can simply call as

var x = 3;
var y = f(x);

Proof : jsperf


If what you want is to let the user enter function with a more classical mathematical language (like x^y), then you'd better start importing a mathematical expression parser.

An example of such a library : Silent Mat's evaluator

8
  • What about the ^ for exponentiation, as delnan pointed out? Jul 1, 2013 at 8:59
  • 1
    @JanDvorak There are functions in JavaScript just for that, like Math.pow. The point here is not to have to interpret the symbolic expression. Jul 1, 2013 at 9:00
  • 1
    Well, eval definitely is evil. evil, n.: something you should avoid most of the time, but not something you should avoid all the time (C++ FAQ 6.15). This time seems not to be most of it.
    – Jan Hudec
    Jul 1, 2013 at 11:12
  • @JanHudec It's JavaScript, not C++. Most "eval is evil" stances are just FUD. Jul 1, 2013 at 11:13
  • 2
    C++ does not have many evil constructs. It was designed by an expert to ease the work of other experts. It has many constructs that have been widely misused by inexpert programmers. Jul 1, 2013 at 13:07
4

You don't want to evaluate Javascript functions. You want to evaluate some subset of the computable functions from the reals to the reals. So eval doesn't do what you want, although in principle you may be able to abuse it for that. Apart from this philosophical objection, if you want to use ^ for exponentiation, you can't use eval because it uses Javascript syntax where ^ is binary xor.

If you just want to be done quickly and leave this project, you can use eval (especially since this apparently runs on the client site, so the potential for abuse is limited). But the right thing(tm) to do would be using an expression parser specifically for the kind of syntax you want to allow, coupled with an evaluation routine for the parsing output.

It's not that hard to write such a thing yourself, and quite fun. I'd use either the shunting-yard algorithm or a top down operator precedence parser. Alternatively, use an existing library as recommended in the comments.

16
  • I don't want to use ^ for exponentiation. It's up to the user to use the correct syntax as I've noted in the application. I just used this here to make it easier to read. Jul 1, 2013 at 9:05
  • Eval is supposed to be efficient, whereas your ad hoc interpreter is never going to reach the underlying javascript performance. Therefore, the best approach is to compile your simple DSL into JavaScript and then eval the resulting code.
    – SK-logic
    Jul 1, 2013 at 9:10
  • @SK-logic If the evaluation of the function is the bottleneck, yes. Otherwise it's probably not worth the extra twenty lines. While we're talking about performance, note the point of another answer that repeated eval would needlessly parse the JS code again and again.
    – user7043
    Jul 1, 2013 at 9:13
  • @delnan, and for plotting it is a bottleneck indeed (since it's an inner loop body). And even if performance is not an issue, there is not much point in reinventing an execution engine if one is already available.
    – SK-logic
    Jul 1, 2013 at 9:15
  • @SK-logic I've never created a plotter, so I refrain from guessing. And in my experience, just evaluating simple math is simpler than robustly mapping it to another language. For such simple operations, evaluation is trivial.
    – user7043
    Jul 1, 2013 at 9:18
2

A lot of people who know eval is dangerous on the server side also reflexively shun it on the client side. There is a huge difference. It is not a security hole to be able to execute your own arbitrary code on your own computer. The only time to be concerned about eval security on the client side is if you're using it to execute code from an untrusted third party, for example from email or a twitter feed.

However, there are other factors to consider. The eval solution is going to be much simpler for basic functionality, but much more difficult to add things like useful error messages. You may end up implementing your own parser anyway to add those sorts of features.

There are also performance considerations, but I think the difference is likely to be negligible. eval will probably have higher startup times, but faster execution times.

Personally, I would use eval for a tool for my own use or within my company, for its simplicity of development. For wider distribution, I would want the polish a custom parser can provide.

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.