javascript - 在 JavaScript 中重新分配函数声明

标签 javascript function gwt singleton

现在我正在调试自 Firefox 46 以来我的 GWT(版本 2.5.1)应用程序中出现的一些奇怪错误。GWT 生成的 JavaScript 代码包含此模式的多个实例:

function nullMethod() {
}

var v;
function f() {
   f = nullMethod;
   v = { name : 'Joe' };
   console.log("called");
}

// this is called from multiple places 
console.log((f(), v).name);
console.log((f(), v).name);
console.log((f(), v).name);

似乎这以某种方式实现了单例模式。但由于某种原因,这并不能阻止再次调用初始声明的方法。字符串“called”被多次打印到控制台。

但是,如果我尝试通过一些测试来重现这一点,一切都会按预期进行。上面的观察结果是通过将控制台输出添加到生成的代码 (>5MB) 中得出的。

现在是非常奇怪的事情。如果我添加“console.log(f.toString())”作为函数的第一个语句,它将在第一次调用时打印初始函数。所有进一步的调用都会打印 nullMethod。

有人可以解释一下可能是什么原因吗? IE11 运行良好。 Chrome 与 Firefox 46 存在相同的问题。自从引入此行为以来,我只是没有找到旧的 Chrome 版本来验证。覆盖以这种方式声明的函数是否有效?

jsbin.com 在函数重新赋值行给出警告:

Line 6: 'f' is a function.

最佳答案

本例中的方法 f 是 Java 静态初始值设定项。多次运行它会导致模拟的 Java 出现问题,Java 预计只能在首次引用或加载类时运行一次(忽略类加载器问题,因为 GWT 不模拟类加载器)。

但是,足够旧的 GWT 副本将代码块包装在 try/catch block 中(iirc 这与 IE6 问题有关),并且当时, JS 作用域规则存在一些模糊性,这使得该代码能够一致地工作,因为所有浏览器都支持这一点。这被称为“草率模式自定义函数”。

作为 ES2015 的一部分,已决定 try block 的作用域与外部“函数托管” block 的作用域不同(即,当您将某些内容声明为 function foo() {...},它存在于高级范围中)。在 https://github.com/tc39/ecma262/issues/162 上查看大量对此的讨论。 .

此更改意味着一些以前正常的程序不再正常工作 - 一度包括 Google Inbox 和其他程序。

更新到较新版本的 GWT,或使用不再将每个顶级 JS block 包装在旧 GWT 中的自定义链接器 应该可以解决此问题。如果您仍然必须支持任何需要这种行为的古老浏览器(通过足够的代码考古学,我相信我们可以找出 GWT 最初这样做的原因,但我还没有这样做),您将必须找到一个在古老的和前沿的浏览器中都有效的妥协。

关于javascript - 在 JavaScript 中重新分配函数声明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37350010/

相关文章:

javascript - jQuery:页面代码和document.ready代码之间的共享功能

javascript - 当用户离开页面时使用 redux-saga 保存进度数据

c++ - 在类内部而不是在 C++ 外部定义成员函数?

Javascript 页面重新加载或元标记刷新方法?

css - 内联 CSS 不适用于添加的小部件

javascript - 检测没有超链接的文本中的 URL 并用超链接替换普通 URL?

javascript - 如何从单击按钮时拖入拖放区的 div 获取 javascript 的 id

javascript - 在 JavaScript 中,这种对变量进行赋值的函数有用吗?

css - gwt - 如何重置 GWT 应用程序的 CSS?

java - GWT Junit Ant 警告 : multiple versions of ant detected in path for junit