7 ms·
The author critically misunderstands the way that `this` gets set, and in doing so has developed a significantly overcomplicated mental model. This is exemplif
by couchand 12y ago
The author critically misunderstands the way that `this` gets set, and in doing so has developed a significantly overcomplicated mental model. This is exemplified in the statement:
You can use this in any function on an object to refer to other properties on that object. This is not the same as an instance created with new. ... Note, there was no use of new , no Object.create and no function called to create obj.
This is exactly the same behavior that you see on an object method reference, and drawing any distinction at all makes understanding the behavior of this harder than it needs to be.
In nearly every case (with the exception of bind, call and apply) the this variable is set at the CALL SITE of the function, NOT THE DEFINITION. Note that in the three other cases, you still aren't setting this at the definition.
The reason you get this behaving as the author describes on objects created with new is only (as the author nearly, but not quite, realizes) because you called the function in the form:
thing.method()
Specifically, it is the object reference that sets the this context within the method call.
You can be sure that the object literal case is just the same. You don't need to call new to get an object reference that has a prototype chain: namely, an object literal is instantiated with the prototype Object. You can verify this is true with a simple:
thing = {}
thing.hasOwnProperty === Object.hasOwnProperty
...and so forth.
- deleted 12y ago[deleted]
- btipling 12y ago> The author critically misunderstands the way that `this` gets set... I don't actually. (I'm the author) I know that the this key word is executed at run time to figure out what this is. It is true there are simpler ways to explain this and this blog post isn't that. I link to such a post at the bottom of my own. These are just some examples. There's also more to that blog post than what everyone is discussing, like returning from a constructor and global this in node.js and accessing this in eval and more. Anyway, I didn't submit this to HN and hadn't intended to. I also didn't intend to sit here tonight and put on a thick skin to deal with all this criticism for something I wrote months ago.
- S_A_P 12y agoDon't take the criticism too hard. I enjoyed the post. I don't regularly write JavaScript so I found many points helpful. There is potential for pedantry here on HN, so dont take offense. I appreciate the post...
- xanderjanz 12y agoThe article was a nice refresher about 'this' subtleties, but it put too much work into contrasting it against Java's this, instead of just laying out the actual JS rules. To me, 'this' is JS is a lot more self explanatory than this is Java. And your article doesn't make that apparent. In JS this is just another object, like any other object. It follows the exact same scoping rules as every other object.
- VieElm 12y ago>In JS this is just another object, like any other object. You are mistaken, "this" is not an object nor a variable, it's a keyword and behaves differently than variable scope. Consider closures for example.
- DonHopkins 12y agoAnd the tragic thing about "this" being a magic keyword that looks up a dynamic value in the runtime, instead of a normal lexically scoped variable like it appears, is that 90% of the time "this" is exactly the thing you want a closure to close over, so you have to do ridiculous stuff like "var self = this;". Even knowing this rule very well and being totally hard core OCO (Obsessive Compulsive ORDER, not Disorder) about the code, I still make "this" mistake ALL THE TIME, so whenever something weird happens, "this" mistakes are the first thing I look for. "this" is such a terrible design flaw, it bites me even when I'm expecting it.
- marrs 12y agoI'd say I use `this` outside of lexical context at least as much as I do within, and I rely on this's behaviour a lot when developing a DSL. It enables some rather elegant patterns, actually.
- xiaoma 12y agoEven more simply, I'd just say: 1) The keyword "this" refers to whatever is left of the dot at call-time. 2) If there's nothing to the left of the dot, then "this" is the root scope (e.g. Window). 3) A few functions change the behavior of "this"—bind, call and apply 4) The keyword "new" binds this to the object just created So if you're using the value of "this" in someFunction... thing.someFunction(); // this === thing someFunction(); // this === Window new someFunction(); // this === the newly created object It's as simple as that. It's a very useful keyword.
- RobertKerans 12y agoWow. I don't think this is a particularly hard concept, but that's an excellent way of visualising it and will definitely help when I'm debugging.
- ebi 12y agoThis is exactly how I explain what "this" is :)
- no_gravity 12y agoCan this model explain what "this" is in the context of an event handler? o={ f: function() setTimeout(1000,console.log(this)) } o.f() http://jsfiddle.net/5bh7yot5/ http://jsfiddle.net/5bh7yot5/
- deleted 12y ago[deleted]
- zenojevski 12y agoThe way you've written this code, `this` refers to `o`, as it has been evaluated at the time of execution of `f()` (first case) rather than inside the `setTimeout` callback, at which point it'd be `Window` (second case). So yes. Basically your code is doing this right now: o.f = function(){ console.log(this); // logs `o`, returns `undefined` setTimeout(1000, undefined); }); If you did this: o.f = function(){ setTimeout(1000, function(){ console.log(this); }); }; Then it'd be `Window` as in rule #2.
- danabramov 12y agoIt helped me immensely when I realized obj.method(); is a sugar for obj.method.call(obj); Similarly, this picture helped me understand `bind`: http://i.stack.imgur.com/StZOr.png http://i.stack.imgur.com/StZOr.png The a-ha moment for JS is when you realize it's a way simpler language than you thought it was.
- jameshart 12y agoYes - the trick with JS is to realize it has this functional core, and every object has an __proto__ property, and then most of its syntax is syntactic sugar over the top of that. new method() is syntactic sugar for something like var _tmp = {}; _tmp.__proto__ = method.prototype; _tmp.call(method);