Closure编译器警告“危险使用全局this对象”?

18
亲爱的朋友们,Closure Compiler在Advanced Mode下会出现警告,其中下划线显示{this.}。
JSC_USED_GLOBAL_THIS:危险地使用全局this对象,在第200行第33个字符处 hovers[i4].onfocus = function() {this.className += "Hovered";}
JSC_USED_GLOBAL_THIS:危险地使用全局this对象,在第201行第32个字符处 hovers[i4].onblur = function() {this.className = this.className.replace(/Hove...

JSC_USED_GLOBAL_THIS:危险地使用全局this对象,在第201行第49个字符处 hovers[i4].onblur = function() {this.className = this.className.replace(/Hove...

JSC_USED_GLOBAL_THIS:危险地使用全局this对象,在第218行第38个字符处 buttons[i5].onmouseover = function() {this.className += "Hovered";}
问题1:这种用法有何危险? 问题2:我应该更改这个代码吗? 问题3:我如何改进/解决这段代码?
谢谢!

1
请参见警告-全局this对象的危险使用,这是一篇更旧的、涉及更具体问题和一些不错答案的帖子。 - MvG
3个回答

19

如果您知道"this"变量的类型,可以使用JsDoc声明它,以防止编译器抱怨:

hovers[i4].onfocus = 
/** @this {Element} */
function() {this.className += "Hovered";}

注意:这假定您确定“this”变量的类型确切无疑。这可能比看起来更加困难。例如:

foo.doSomething = function(x) { this.bar = x; }
foo.doSomething("Hello");
你应该知道,在doSomething中的"this"指的是foo。然而,如果你使用Closure编译器的高级模式,编译器可能会“压缩”foo命名空间,最终结果可能是:
a = function(x) { this.b = x }
a("Hello");

在这种情况下,将foo.doSomething“平铺”为单个全局变量a。因此,“this”变量显然指向全局对象!你的代码会出问题!

因此,Closure编译器强烈警告您不要在可以被平铺的函数中使用“this”。但是,在构造函数和原型函数中使用“this”则没有此警告。

为了解决这个问题,最好避免使用“this”,而是使用命名空间本身:

foo.doSomething = function(x) { foo.bar = x; }
foo.doSomething("Hello");

6
对于定义类的任何函数,应使用 @constructor JSDoc 来消除此警告。这是谷歌推荐用于此类警告的方法。 - marcinkuzminski

12

“this”在不同的上下文中可能有不同的含义,因此它会准确地告诉你这一点。您可以使用闭包来代替:

而不是

hovers[i4].onfocus = function() {this.className += "Hovered";}

有:

hovers[i4].onfocus = function(self) 
{
    return function() {self.className += "Hovered";}
}(hovers[i4])

17
“dangerous use of this”不是在试图告诫用户“此”在不同上下文中具有不同含义,它是在警告用户,如果编译器决定压缩命名空间,任何使用“this”的地方都会指向错误的对象,并且会破坏代码。这是一种与编译器执行的优化完全相关的警告。 - Stephen Chung
@Stephen Chung:嗯,我的意思和你一样。如果你认为我说错了话,随时可以编辑我的回答——英语不是我的母语,有时可能会表达不清楚 :) - Andrey

8

只是为了补充一下 @marcinkuzminski 对 @stephen Chung 的回答所做的评论的示例

 /**
 * Model for ListBox
 *
 * @constructor <-- add this to remove the warning
 */
MyProject.ListBoxModel = function ( data ){

  this.data_  = data || {};   /* this gives warning */
};

来源: https://developers.google.com/closure/compiler/docs/js-for-compiler

本文将介绍如何使用Google Closure Compiler来压缩和优化JavaScript代码。Closure Compiler是一个强大的工具,可以通过消除未使用的代码、缩小变量名并简化代码来减小文件大小,从而提高网站性能。


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