| The this keyword is confusing, it's good to see posts clarifying it. However, while the rule in the post will be right in many cases, this list is incomplete, even for some common usages of this, and might lull folks into a false sense of security: 1. "To the left of the dot" should be "to the left of the dot or bracket". E.g. o["foo"]() also passes o as this. 2. When you pass callbacks to built-ins like forEach, you can supply a thisArg, and if you don't, this will be bound to undefined (http://es5.github.com/#x15.4.4.18). (EDIT): Copying from cwmma below. Some callbacks, like setInterval and setTimeout, pass the global object rather than undefined. I suspect that DOM callbacks tend to use the global object and JS callbacks tend to use undefined, but that's not a blanket statement by any means. 3. This isn't purely JS, but when interacting with the DOM, this is also implicitly bound as a DOM element in event listeners. E.g. document.addEventListener('click', function() { console.log(this); }) will print the document object when you click on the page. This is quite relevant for any JS web development; if it makes it easier to conceptualize, imagine that the browser is calling a method with the DOM element to the left of the dot. 4. When the caller is strict mode code and the function is called without method-call syntax, undefined is passed as the this argument rather than the global object. You should always use strict mode to avoid accidentally handing the global object around (in strict mode, the "set to global" option is skipped in http://es5.github.com/#x10.4.3). 5. When using this at the toplevel (which is allowed), it is bound to the global object even in strict mode (http://es5.github.com/#x10.4.1.1). And a few more esoteric ones: 6. In addition to call and apply, Function.prototype.bind() can also change the this parameter of a function, and violate the "left of the dot or bracket" rule (http://es5.github.com/#x15.3.4.5, see boundThis). 7. Inside a with() {} block (which you should never use, but we're trying to cover our bases here), this is bound to the object passed to with in the parentheses. 8. If a property is a getter or a setter, this is bound to the object to the left of the dot or bracket in the field access or assignment expression. This actually matches the rule in the post except for the fact that the "call time" is implicit; there are no () in the expression o.x, but it may call a getter function for x that passes o as this (http://es5.github.com/#x8.12.3). (EDIT): One more doozy: 9. The dot and bracket operators implicitly convert primitives like numbers, strings, and booleans to objects, so it's not exactly what's to the left of the dot: Number.prototype.identity = function() { return this; }
var x = 5
var x2 = x.identity()
typeof x2 === 'object' (true!)
typeof x2 === 'number' (false!)
You can get the raw primitive if you make the function strict: Number.prototype.identity2 = function() { "use strict"; return this; }
var x = 5;
var maybe_five = x.identity2();
typeof maybe_five === 'object' (false)
typeof maybe_five === 'number' (true)
Please correct me if I've forgotten any... |