views:

486

answers:

3

This link shows you that jQuery uses (new Function("return " + data))(); for older browsers, to parse a JSON string instead of eval().

What are the benefits of this? What if the JSON string isn't safe?

+1  A: 

http://www.json.org/js.html

The eval function is very fast. However, it can compile and execute any JavaScript program, so there can be security issues. The use of eval is indicated when the source is trusted and competent. It is much safer to use a JSON parser. In web applications over XMLHttpRequest, communication is permitted only to the same origin that provide that page, so it is trusted. But it might not be competent. If the server is not rigorous in its JSON encoding, or if it does not scrupulously validate all of its inputs, then it could deliver invalid JSON text that could be carrying dangerous script. The eval function would execute the script, unleashing its malice.

What exactly do you mean with safe? At least malicious code is not executed ;)

See also: http://stackoverflow.com/questions/945015/alternatives-to-javascript-eval-for-parsing-json

Another point might be, that new Function() is considered to be a little faster than eval.

Update:

You can basically read about the same arguments in the comments on jQuery's .parseJSON() function.

Felix Kling
Sounds like a good answer for an odd question =)
Fabiano PS
but with `new Function();` malicious code is still executed.
Luca Matteis
How is this a good answer? Luca wanted to know how `eval` is different from `new Function(...)`, and this just says what's wrong with `eval`.
Gabe
@gabe: Well he did not state that he wants know the differences. He wanted to know the benefits which are *security* and *speed*.
Felix Kling
Felix: Luca wanted to know how `new Function()` is better than `eval`. You answered that `eval` is dangerous, while incorrectly implying that `new Function()` is somehow less dangerous. In fact it appears that your second point (it's faster) is the only correct part of your answer.
Gabe
@gabe: actually that second part appears to be only true in old-ish versions of Firefox, but it's a major improvement for Firefox compared to the minor deficiencies in other browsers - http://weblogs.asp.net/yuanjian/archive/2009/03/22/json-performance-comparison-of-eval-new-function-and-json.aspx
Andy E
+6  A: 

As to why jQuery specifically uses new Function(), John Resig answered this on the jQuery forums

Using eval causes all sorts of problems for code minifiers since it's not clear what could be executing in the eval. Looking at the last results from that run it looks like new Function is fairly equivalent to eval and even slightly faster sometimes. The one exception was Safari 4 - but those results are dated, Safari 4 shipped with a native JSON.parse implementation, which we use.

Nick Craver
+15  A: 

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.
bobince