This “this” is Your This
Tuesday, October 12, 2010 | 2:04 PM
In a past blog post, we talked about how Closure Compiler makes it easier to share common JavaScript by ensuring that everybody declares what variables they own.
Global variable uniqueness is something that we added checks for fairly early on. Some restrictions are less obvious. In this blog post we’ll talk about the this
keyword.
Suppose Nathan wants to outsource hot dog eating contests, so that we don’t need an instance of Nathan to run one. To do so, he takes runHotDogContest
and unpackHotDogs
off the prototype, and makes them into static methods. The code now looks like this:
Nathan.runHotDogContest = function(player, boxes) {
for (var i = 0; i < boxes.length; i++) {
player.eatHotDogs(this.unpackHotDogs(boxes[i]));
}
};
I want to run 2 hot dog contests, so naturally, I write:
var run = Nathan.runHotDogContest;
run(joey, crateA);
run(kobayashi, crateB);
The code fails with an error that
unpackHotDogs
is not defined on this
. The reason is subtle. To the person writing Nathan.runHotDogContest
, this
and Nathan
seem like interchangeable variables. And as long as you’re testing them by invoking them as:Nathan.runHotDogContest(joey, crateA);
Nathan.runHotDogContest(kobayashi, crateB);
then they will be interchangeable.
In fact,
this
is a secret argument to the function. It’s much like any other function argument, except that it appears on the left side of the function call instead of on the right side. So Nathan.runHotDogContest(...)
passes Nathan
as the this
argument, and run(...)
passes null
as the this
argument (which JavaScript helpfully coerces to window).To make Closure Library usable, the library authors and the library users need to agree on what the arguments to a function mean. This includes
secret
arguments like this
. So we’ve agreed that only constructors and prototype methods may use this
, and the this
argument must be an instanceof the relevant constructor. Closure Compiler enforces this in --warning_level VERBOSE
, and will often emit a warning if it sees this
used in a dangerous place.If you’re writing a function that expects an unusual
this
context, you can explicitly document it with the @this
annotation, and the warning will go away.Good luck with all of this!
2 comments:
Alfonso said...
Nick,
Having just discovered closure tools via a module in the fantastic play framework, I wonder, what does the future hold for the library? (since the last post on is October 2010)
Thanks
Allan
January 14, 2011 at 1:46 AM
Eric said...
Very interesting. JavaScript has a lot of quirks with the "this" keyword, and this is one of them I didn't know about until now.
Thanks for sharing and your work on the library.
July 5, 2011 at 10:02 AM
Post a Comment