19

编辑:明确地说,我不是在寻找有关功能所暗示的各种问题的定性价值的建议或意见——我也不是在寻找实际问题的可靠解决方案;我只是在寻找标题中问题的技术性、可验证的答案。我已将问题附加到不符合要求的浏览器列表中。

使用函数的.toString方法通常会呈现该函数的源代码问题是没有指定这种行为——规范没有对应用于函数时的行为做出任何承诺。Chrome 的控制台甚至会告诉您(当您将函数以外的任何内容传递给 时Function.toString.call),Function.prototype.toString 不是通用的

This blog post建议这可以用作为多行字符串生成可读语法的方法(通过将字符串作为多行注释存储在无操作函数的主体中)。作者建议在编写Node.js应用程序的上下文中使用这种用法,并指出这种行为是可靠的,因为 Node.js 在受控环境中运行。但是在 Javascript 的原生网络中,任何东西都可以出现并解释它,我们不应该依赖未指定的行为。

但在实践中,我设置了一个小提琴,它呈现一个选择框,其内容由一个大的多行字符串确定以测试代码,以及我工作站上的每个浏览器(Chrome 27、Firefox 21、Opera 12、Safari 5 , Internet Explorer 8) 按预期执行。

当前哪些 Javascript 引擎的行为如下?

鉴于:

function uncomment(fn){
  return fn.toString().split(/\/\*\n|\n\*\//g).slice(1,-1).join();
}

以下:

uncomment(function(){/*
erg
arg
*/});

应该输出:

erg
arg

不合格浏览器列表:

  • 火狐 16
  • …</li>
4

2 回答 2

6

当前的 Javascript 引擎有哪些不这样的行为?

鉴于您尚未定义“流行”,您的问题并没有真正明确定义。IE6流行吗?IE5?IE4?网景导航器?猞猁?正确回答您的问题的唯一方法是枚举您希望支持的浏览器并检查它们。不幸的是 kangax 的表http://kangax.github.io/es5-compat-table/#没有测试 Function.prototype.toString

Chrome 的控制台甚至会告诉您(当您传递除函数或 Function.toString.call 以外的任何内容时),Function.prototype.toString 不是通用的

规范中规定的

规范避免对应用于函数时的行为做出任何承诺

所需的行为在 ECMA-262 版本 1 中指定(从 1997 年开始,http://www.ecma-international.org/publications/files/ECMA-ST-ARCH/ECMA-262,%201st%20edition,%20June%201997 .pdf ) 你必须把它追下来:

由此,我们推断函数是对象。

那么现在什么是 ToPrimitive?

所以我们需要知道 DefaultValue 是做什么的

现在我们只需要找到 Function.prototype.toString 的描述位置:

因此,您可以保证获得正确的 javascript 表示形式(不是一些 IL gobbledegook),但不一定带有注释。例如,该技术在 Firefox 16 中中断(但您必须询问它是否是最新的)。

于 2013-06-07T16:49:03.787 回答
1

因此,Kangax 回到了主题(他对 Angular 在客户端代码中使用这种 hack 的核心功能这一事实很感兴趣)并编写了实践分析,并制作了函数反编译状态的测试表在 Javascript 中

要点是:

  • 该技术仅对用户定义的函数声明是远程可靠的。
  • 一些旧的移动浏览器仍然会崩溃功能代码,据称是出于性能原因。
  • 其他旧浏览器会显示优化的代码,就像你可能从 Closure Compiler 中得到的一样。
  • 还有一些人会删除评论并改变空格。
  • Internet Explorer 偶尔会在函数周围添加注释和空格。
  • AngularJS 团队似乎认为这种技术足够强大,可以在没有明确警告的情况下包含在他们的库中。然后他们标记(!)代码并重新评估它(!)。

出于我的目的,这让我有理由相信我可以做一些相对不要求的事情,比如通过如下解析来检测函数是否具有大写名称:

/function\s*[A-Z]/.test( fn )
于 2014-10-20T10:21:55.483 回答