Javascript 闭包编译器警告“危险使用此对象的全局对象”?

Javascript 闭包编译器警告“危险使用此对象的全局对象”?,javascript,jquery,debugging,google-closure-compiler,Javascript,Jquery,Debugging,Google Closure Compiler,亲爱的朋友们,闭包编译器在高级模式下给出此警告,并在{this. JSC_使用了_GLOBAL_THIS:危险地使用第200行字符33处的全局THIS对象 hover[i4].onfocus=function(){this.className+=“hover”} JSC_使用了_GLOBAL_THIS:危险地使用第201行字符32处的全局THIS对象 悬停[i4].onblur=function(){this.className=this.className.replace(/Hove… JSC

亲爱的朋友们,闭包编译器在高级模式下给出此警告,并在
{this.

JSC_使用了_GLOBAL_THIS:危险地使用第200行字符33处的全局THIS对象
hover[i4].onfocus=function(){this.className+=“hover”}

JSC_使用了_GLOBAL_THIS:危险地使用第201行字符32处的全局THIS对象
悬停[i4].onblur=function(){this.className=this.className.replace(/Hove…

JSC_使用了_GLOBAL_THIS:危险地使用了第201行字符49处的全局THIS对象
悬停[i4].onblur=function(){this.className=this.className.replace(/Hove…

JSC_使用了_GLOBAL_THIS:危险地使用第218行字符38处的全局THIS对象
按钮[i5].onmouseover=function(){this.className+=“悬停”}

Q1.这有什么危险?
Q2.我应该改变这个吗?
Q3.如何改进/解决此代码?

谢谢!

“这个”在不同的上下文中可能有不同的含义,所以它确切地告诉您。 您可以改为使用闭包:

而不是

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


如果您知道“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
。但是,如果您使用闭包编译器的高级模式,编译器可能会“展平”
foo
命名空间,您将得到:

a = function(x) { this.b = x }
a("Hello");
foo.doSomething
被“展平”为单个全局变量
a
。在这种情况下,“this”变量显然指向全局对象!您的代码将被破坏

因此,闭包编译器非常坚决地警告您不要在可以展平的函数中使用“this”。不过,您可以在构造函数和原型函数中使用“this”,而不使用此警告

要解决此问题,最好通过使用名称空间本身来避免使用“this”:

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

只是为了举例说明@marcinkuzminski对@stephen Chung answer的评论

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

  this.data_  = data || {};   /* this gives warning */
};
/**
*列表框模型
*

*@constructor“this的危险用法”并不是试图警告用户“this”在不同上下文中的不同含义。它是一个警告,告诉用户,如果编译器决定展平命名空间,“this”的任何用法将指向错误的对象并将破坏代码。这纯粹是一个警告,与编译器执行的优化有关。@Stephen Chung:嗯,我的意思是相同的。如果你认为我说错了,请随意编辑我的答案-英语不是我的第一语言,我可能会把事情的措辞弄错:)对于任何定义类的函数,您都应该使用@constructor is JSDoc来消除此警告。这是google为此类警告推荐的方法。这也是一篇较老的文章,有一个更具体的问题和一些很好的答案。
 /**
 * Model for ListBox
 *
 * @constructor <-- add this to remove the warning
 */
MyProject.ListBoxModel = function ( data ){

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