开发者

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

开发者 https://www.devze.com 2022-12-22 20:01 出处:网络
This link shows you that jQuery uses (new Function(\"return \" + data))()开发者_开发百科; for older browsers, to parse a JSON string instead of eval().

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?


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.


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.


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

0

精彩评论

暂无评论...
验证码 换一张
取 消