在javascript

时间:2016-05-20 14:58:30

标签: 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())”作为函数的第一个语句,它会在第一次调用时打印intial函数。所有进一步的调用都会打印nullMethod。

有人可以解释可能的原因吗? IE11工作正常。 Chrome与Firefox 46具有相同的问题。我从未找到旧的Chrome版本进行验证,因为引入了此行为。覆盖以这种方式声明的函数是否有效?

jsbin.com在功能重新分配行上发出警告:

Line 6: 'f' is a function.

1 个答案:

答案 0 :(得分:1)

在这种情况下,方法f是一个Java静态初始化程序。多次运行会导致模拟Java出现问题,这种问题在首次引用或加载类时只能运行一次(忽略类加载器问题,因为GWT不会模拟类加载器)。

但是,GWT的足够旧的副本会在try / catch块中包含代码块(这与IE6问题有关),当时JS范围规则有些含糊不清因为所有浏览器都支持这个,所以这些代码一致地工作。这被称为“草率模式自定义函数”。

作为ES2015的一部分,已经确定try块与外部“函数托管”的范围不同(即当您将某些内容声明为function foo() {...}时,它存在于高级别中范围)。请参阅https://github.com/tc39/ecma262/issues/162上的大量讨论。

这一变化意味着一些以前理智的程序不再正常工作 - 有一段时间,这包括谷歌收件箱以及其他人。

更新到更新版本的GWT,或者使用不再包含旧GWT中每个顶级JS块的自定义Linker应解决此问题。如果你仍然必须支持任何需要这种行为的古老浏览器(有足够的代码考古,我相信我们可以找出为什么GWT最初做了它,但我还没有这样做),你将不得不找到一个妥协在古代和前沿的浏览器中都有效。