jQuery uses (new Function(“return ” + data))(); instead of eval(data); to parse JSON, why?

The quote in Nick’s answer hints at it. It’s not really a big difference, but the feeling is that eval is ‘worse’ than new Function. Not in terms of security — they’re both equally useless in the face of untrusted input, but then hopefully your webapp is not returning untrusted JSON strings — but in terms of language-level weirdness, and hence resistance to optimisation.

Specifically:

function victim() {
    var a= 1;
    eval('a= 2');
    return a;
}

gives 2. The eval​ed string has operated on victim‘s local variable scope! This is something that a regular user-written function could never do; eval can only do it because it is dark magic.

Using a regular function instead takes away this element of magic:

function victim() {
    var a= 1;
    (new Function('a= 2;'))();
    return a;
}

in the above, the returned a remains 1; the new Function can only operate on its own local variables or the global window.a.

That knowledge allows code analysis tools — which might include JavaScript engines and particularly clever minifiers — to apply more optimisations. For example the second victim function could have the a variable completely optimised away to return 1. One use of eval and a lot of potential optimisations aren’t going to be doable.

Of course in practice for a tiny function like a JSON eval​er, there isn’t going to be a noticeable difference, but in general the thinking is:

  • avoid both approaches wherever possible (they are both disallowed in ECMAScript Fifth Edition’s Strict Mode);
  • if you have to use one, new Function is preferable to eval, unless you really need the code to access the calling function’s local variables.

Leave a Comment