如何防止Google Closure Compiler删除一行代码

3
我有一个函数,其中创建了一个测试元素。在返回函数之前,我将测试元素的引用设置为 null,以帮助防止内存泄漏。但是 closure compiler 删除了这一行,因为它认为这不是必需的(在两种模式下都是如此)。是否有一种注释可以添加以防止删除该行?
function isExample (testElem) {
 var bool; 
 testElem = testElem || document.createElement('div');

 // Do stuff in here to determine `bool`
 // ...

 // Then nullify the reference
 testElem = null; // The compiler removes this line. How do I make it keep it?

 return bool;
}
2个回答

5
不需要这样做。垃圾回收器会执行相同的操作,因此Google Closure Complier只是将其删除。
我不知道任何一个垃圾回收器会在此方面泄漏内存,如果有问题,JS可能会遇到很大的问题。
请记住JS具有函数作用域,这意味着在函数中定义的任何变量一旦执行退出函数就会被垃圾回收。
这是垃圾回收器的基本功能之一,如果js引擎在此方面泄漏内存,那么情况将非常糟糕。
对于旧版IE泄漏问题,您可以尝试通过在null之后添加“testElement = []”来解决编译器问题。

内存泄漏是旧版IE中的一个问题。jQuery和Modernizr在某些函数中都会使元素为空——这一定有原因。 - ryanve
1
@ryanve 在旧版IE中,对于已删除的DOM元素上的事件侦听器会泄漏内存,但对于这种情况不会 :-) - Florian Margaine
@Esailija,是的,在那里没有闭包,这就是为什么我指定“在函数中定义的任何变量”:p - Florian Margaine
将一个空数组赋值给变量不应该起作用 - 编译器仍然可以自由地将其作为死代码删除。如果出于某种原因它确实起作用,那么它将被视为错误并可能在未来被删除。 - Chad Killingsworth
如果编译器在存在引用该值的函数闭包时删除该值,则这是编译器中的错误。如果没有闭包,那么编译器可以自由地删除该值,你应该让它去做。 - John
显示剩余2条评论

2
在这种情况下,编译器是正确的。但是,如果你坚持要保留这段代码,那么你需要使用引号语法来导出值或者使用一个接收对象。
function sinkValue(x) {
  sinkValue[' '](x);
  return x;
}
sinkValue[' '] = function(){};

function isExample (testElem) {
  var bool;
  var obj = { 'elem': testElem || document.createElement('div') };

  // Do stuff in here to determine `bool`
  // ...

  obj['elem'] = null;
  sinkValue(obj);

  return bool;
}

引用语法会防止重命名和死代码消除,因此您将否定该对象属性上的任何这些优化。不过,在这种情况下,您正在延长对象的生命周期超出函数(这似乎与您的意图相反)。
没有注释可以精确指定您想要的内容。您可以在以下讨论中查看相关讨论: 编译器正按照预期执行,即删除无用代码。

1
Chad,该对象未被转义,因此如果这样做有效,它仍可能在将来被消除。使用全局窗口而不是obj会起作用,但绝对是过度杀伤力的。 - John
1
是的,我也担心这个问题。两者都似乎过于复杂了。看起来对于这种情况,您需要复制goog.reflect.sinkValue定义。我会相应地修改答案。 - Chad Killingsworth

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接