【问题标题】:parsing JSON - eval() or function object?解析 JSON - eval() 还是函数对象?
【发布时间】:2010-08-26 11:56:29
【问题描述】:

要解析 JSON,我认为最好的方法是在浏览器中使用原生 JSON 支持。

我一直在寻找一种在原生 JSON 支持不可用的情况下解析 JSON 的好方法。

当我查看https://github.com/douglascrockford/JSON-js/blob/master/json2.js 中的代码时,我的理解是它首先使用正则表达式检查数据是否是有效的 JSON:

if (/^[\],:{}\s]*$/.
test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
replace(/(?:^|:|,)(?:\s*\[)+/g, '')))

然后应用 eval()。

jQuery 首先使用上面的正则表达式执行 $.parseJSON() 来检查它是否是有效的 JSON,然后应用:

return window.JSON && window.JSON.parse ?
    window.JSON.parse( data ) :
        (new Function("return " + data))();

如果原生 JSON 可用,则使用它,否则使用“新函数”。

我在其他任何地方都找不到关于使用函数对象解析 JSON 的信息。哪个是更好的方法 - 使用 eval() 或函数对象?你能解释一下(new Function("return " + data))();到底是做什么的吗?

【问题讨论】:

  • 如果可用,请始终使用本机实现。
  • 我想知道如果本地实现不可用如何解析 JSON
  • 请注意,jQuery 的 parseJSON 是不安全的,因为它无法转义字符 U+2028 和 U+2029,这些字符在 JavaScript 中是行分隔符,但在 JSON 中是有效的原始字符(一个相当糟糕的设计) . parseJSON('"hello\u2028!"'); 在没有原生 JSON 的浏览器上会失败。 json2.js 记得在上一步中转义它们。

标签: javascript jquery json eval function-object


【解决方案1】:

new Function("return "+data) 在这种情况下与 eval 几乎相同。 其中eval直接返回结果,(new Function("return "+data))()做一个匿名函数并执行。

我没有做过基准测试,但我认为new Function 比 eval 慢一点,因为首先创建一个函数,然后对代码进行评估。不要相信我的话,这只是我的大脑思考。

【讨论】:

  • 'new Function' 是否消除了 eval() 的安全问题?
  • 但是为什么使用'new Function'而不是'eval'呢?
  • 这可能是开发人员的选择,但 BGerissens 的回答相当有趣。找到它:forum.jquery.com/topic/…
  • 从我从 jquery 的源代码中了解到,jquery 甚至在应用本机 JSON 解析之前验证数据
  • 是的,没错。 Answer: “不幸的是,浏览器在他们愿意用 JSON.parse 代码解析的 JSON 上并不一致。例如,Chrome 接受了一些我们需要拒绝的无效字符串。此外,我们需要让我们接受和拒绝哪些字符串保持一致(并使用正则表达式进行仔细检查)。”
【解决方案2】:

'new Function' 是执行 eval() 的一种更安全的方法,使用 eval,作用域链中的所有变量都可用于 evalled 的代码,而不是使用 'new Function',它确实在hood,但无法访问作用域链中的变量。变量需要与传递的代码字符串连接。

(new Function("return " + data))();

基本上,创建一个将“数据”转换为对象并返回它的函数,最后一个括号 () 立即调用该函数。由于没有创建对已创建函数的引用,因此垃圾收集器会从对象堆栈中清除已创建函数。

【讨论】:

  • 如果您想安全,请在匿名函数中的某处执行var window;。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-02
  • 1970-01-01
相关资源
最近更新 更多