【问题标题】:Why is toString of JavaScript function implementation-dependent?为什么 JavaScript 函数的 toString 依赖于实现?
【发布时间】:2015-03-16 06:38:29
【问题描述】:

来自EcmaScript 5 specification

15.3.4.2 Function.prototype.toString()

返回一个依赖于实现的函数表示。此表示具有 FunctionDeclaration 的语法。请特别注意,表示字符串中空格、行终止符和分号的使用和放置取决于实现。

为什么它依赖于实现?让它输出由函数的原始代码组成的标准化字符串应该不会太难。此外,我可以提出的原因(例如优化)似乎并没有被过多使用,因为几乎所有浏览器都将原始代码作为 toString 的结果。

如果 toString 不依赖于实现,因此将被标准化为函数的原始代码(以标准方式处理新行等),它不会使可以在 JSON 上包含函数吗?

我确实意识到 JSON,尽管它的名字,独立于 JavaScript,因此函数不应该是它的一部分。但是这种方式理论上可以将函数作为字符串传递,而不会失去跨浏览器的支持。

【问题讨论】:

  • specification says "此表示具有 FunctionDeclaration 的语法",因此结果必须在语法上仍然正确。与实现相关的部分仅与空白等有关。
  • @RobG:我认为你是对的。结果是其他函数的可执行函数,而不是包含本机代码的函数,例如 alert。首先将我带到这里的实际用例是使用 this 进行依赖注入,例如 AngularJSthis 文章中描述了与此不标准相关的多个问题。

标签: javascript json ecmascript-5


【解决方案1】:

在内部,Function.prototype.toString() 必须获取函数的函数声明代码,它可能有也可能没有。根据MDN页面,FF以前是反编译函数的,现在和函数一起存储声明,所以不用反编译了。

从 Gecko 17.0 (Firefox 17 / Thunderbird 17 / SeaMonkey 2.14) 开始, Function.prototype.toString() 已经通过保存实现 函数的来源。反编译器被删除

*https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/toString

反编译需要额外的工作。存储它需要额外的内存。给定的ECMAscript 实现可能有不同的资源需求。

此外,如果它被反编译,那取决于它最初是如何存储的。引擎可能无法返回原始的 cmets,因为在评估函数时它没有存储它们。或者如果引擎折叠它们,空格/换行符可能会有所不同。或者引擎可能已经优化了代码,例如忽略了unreachable code,从而无法在toString() 调用中返回该代码。

...有些引擎会省略换行符。其他的则省略了 cmets。和别的 省略“死代码”。其他包括围绕 (!) 函数的 cmets。和 其他人完全隐藏源...

*http://perfectionkills.com/state-of-function-decompilation-in-javascript/

这些只是Function.prototype.toString() 依赖于实现的几个原因。

【讨论】:

    猜你喜欢
    • 2018-04-13
    • 1970-01-01
    • 2015-09-16
    • 1970-01-01
    • 1970-01-01
    • 2016-05-05
    • 1970-01-01
    • 1970-01-01
    • 2019-02-02
    相关资源
    最近更新 更多