18

Dear folks, Closure Compiler gives this warnings in Advanced Mode, underlining {this.

JSC_USED_GLOBAL_THIS: dangerous use of the global this object at line 200 character 33 hovers[i4].onfocus = function() {this.className += "Hovered";}

JSC_USED_GLOBAL_THIS: dangerous use of the global this object at line 201 character 32 hovers[i4].onblur = function() {this.className = this.className.replace(/Hove...

JSC_USED_GLOBAL_THIS: dangerous use of the global this object at line 201 character 49 hovers[i4].onblur = function() {this.className = this.className.replace(/Hove...

JSC_USED_GLOBAL_THIS: dangerous use of the global this object at line 218 character 38 buttons[i5].onmouseover = function() {this.className += "Hovered";}

Q1. Whats so dangerous about this?
Q2. Should I change this?
Q3. How do I improve/solve this code?

merci!

Stephen Chung
  • 14,497
  • 1
  • 35
  • 48
Sam
  • 15,254
  • 25
  • 90
  • 145
  • 1
    See also [WARNING - dangerous use of the global this object](http://stackoverflow.com/q/4036949/1468366) which is an older post, with a more specific problem and some nice answers as well. – MvG Nov 18 '14 at 22:47

3 Answers3

19

If you know the type of the "this" variable, you can declare it with a JsDoc to stop the compiler from complaining:

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

Caveat: this, however, assumes you know for sure the type of the "this" variable. This may not be as easy as it seems. For example:

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

You would have known that "this" in doSomething refers to foo. However, if you use the Advanced Mode of the Closure Compiler, the compiler may "flatten" the foo namespace and you'll end up with:

a = function(x) { this.b = x }
a("Hello");

with foo.doSomething being "flattened" to a single global variable a. In this case, the "this" variable obviously points to the global object instead! Your code will break!

Therefore, the Closure Compiler is quite adamant in warning you not to use "this" in functions that can be flattened. You may use "this" in constructors and prototype functions without this warning though.

To resolve this, it is better to avoid using "this" by using the namespace itself:

foo.doSomething = function(x) { foo.bar = x; }
foo.doSomething("Hello");
Stephen Chung
  • 14,497
  • 1
  • 35
  • 48
  • 6
    For any functions that defines classes you should use @constructor is JSDoc to get rid of this warning. This is a way google recommends for this type of warning – marcinkuzminski Sep 05 '11 at 23:35
12

"this" might have different meaning in different context, so it tells you exactly that. You can use closures instead:

Instead of

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

have:

hovers[i4].onfocus = function(self) 
{
    return function() {self.className += "Hovered";}
}(hovers[i4])
Andrey
  • 20,487
  • 26
  • 108
  • 176
  • 17
    "dangerous use of this" is not trying to warn the user regarding different meanings of "this" in different contexts. It is a warning telling the user that, in case the compiler decides to *flatten* the namespace, any usage of "this" will point to the wrong object and will break code. It is a warning purely having to do with optimizations performed by the compiler. – Stephen Chung Mar 29 '11 at 06:28
  • @Stephen Chung:Well, I meant the same thing. If you think I misspoke, feel free to edit my answer - English is not my first language and I might misphrase things :) – Andrey Mar 29 '11 at 16:59
8

Just to add example of what @marcinkuzminski added comment to @stephen Chung answer

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

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

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

aked
  • 5,625
  • 2
  • 28
  • 33