Finally someone makes sense of JavaScript's this keyword
javascriptweblog.wordpress.com
javascriptweblog.wordpress.com
Now, I just put
var that = this;
at the top of very method and use 'that' everywhere in the function.Another way is jQuery.proxy(), though that works best for calling a method with the correct context.
Or the numerous ``bind`` functions and methods (which do the same thing).
In fact, ES5's Function prototype even grew a ``bind`` method[0], which is used to partially apply a function (both to bind it to a ``this`` and to bind it to an arbitrary number of arguments).
Some libraries (e.g. underscore) also have a shortcut to bind all methods of an object (or only a subset of those)[1], handy when using methods as event or deferred callbacks
[0] https://developer.mozilla.org/en/JavaScript/Reference/Global...
var _this = this; //vanilla
var $this = $(this); //jQuery
Though, I have encountered people who are really against the $var for stylistic reasons - so ymmv. initComponent: function() {
var me = this;
me.callParent();
...
Thanks for explaining the rationale; I'd never paid enough attention to understand why they were doing that.Something I also find helpful is reminding myself that I'm not just writing a function, but a method for the current object (referenced by 'this').
I agree that in the case where you're creating a closure, you need to create a reference to the scope referenced by 'this' in order to 'enclose' it, however, that doesn't make it a best practice, all the time, as many responses are suggesting.
Environment model of evaluation, http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-21.html...
Metacircular evaluator, http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-26.html...
The environment model is crucially helpful. Applying it to Javascript, think of bound functions (ones which are methods on instantiated objects) implicitly having a 'let this = instance' statement prepended to their bodies.
++x+x++
x >> 6 > y >> 6
5 % 2 / 5 * 5 + 1Except that Javascript under normal circumstances doesn't have bound functions. A method (a function property on some object) is unbound unless you go out of your way to bind it. So it only conceptually has that "let this = ..." prepended to it within the duration of an invocation that's using property access to get the function.
In other words, JS doesn't include "this" in a function's closure, which is where a lot of the confusion comes from.
I found this article to be a little dense if a less experienced js dev is trying to read it. That being said, if you really want to understand javascript as a language you have to understand "this".
I recommend starting with the 5 examples of how "this" gets assigned. Keep reading those until you understand what they are saying. Then go back and read the entire article again, perhaps a couple of times.
I promise that once it sinks in, you'll be a better javascript programmer.
What really convinces me not to use it is that I can easily write my programs without it and they come out better. Specifically, they come out with less coupling.
Is that like pointers? No, pointers are not an ill-defined concept. People get into trouble with pointers because they're a sharp tool. Some sharp tools are nevertheless indispensable, as pointers are to C. Javascript's this is not a sharp tool, it's a hodgepodge.
Pointers take you closer to the machine. That can be useful, especially for efficiency. What does JS this take you closer to? A complicated evaluation model that has nothing intrinsically to do with anything other than itself. Since its cost is high (in complexity) and its benefit zero (relative to other ways of writing JS), why invest in it? There is a no-brainer here: in exchange for expending less effort, I get simpler programs. Meanwhile I can work at understanding other things that are beautiful and/or useful.
I would disagree with that.
The concept behind "this" is actually pretty simple and well-defined: it's part of the execution context that every function has in Javascript...and it's behavior is predictable based on a small set of principles outlined in the OP.
What those various examples demonstrate is that it's a dynamic concept (an important distinction imho). It's this property which gives a lot of novice developers trouble, but it's also what makes it extremely powerful.
The "effort" you speak of is the extremely minor effort of remembering how "this" behaves in a given scenario (which again, is basically one of several well-defined possibilities).....as opposed to the effort of coding "around" using "this" which will add just as much complexity to your code overall.
To me your suggestion sounds like saying you should only buy what you can pay for with exact change because it's too much "effort" to do some simple arithmetic each time to determine if you've received the correct change.
That's true of course, but this also hinders you in what you can do, and requires effort itself.
I would say both strategies have their benefits and drawbacks, but are ultimately comparable. You can certainly code "around" the this keyword; for example by using closures to create custom types instead of a constructor...
IMHO, avoiding either strategy is the wrong way to go. What you should do is evaluate each situation and determine which strategy offers the best combination of benefits and drawbacks.
In my example, using a closure might be more expressive in some ways, etc etc... but it consumes more memory, will break the instanceof operator, etc etc. There's always trade-offs.
It may be that most of your JS code doesn't require the use of "this", but if a programmer is not able to understand it and use it effectively when the situation calls for it, they will never be complete as a JS coder.
"This" causes hidden coupling. The difficulty isn't remembering how "this" works (that's an annoyance), it's figuring out how a program that uses it heavily works when all the action-at-a-distance kicks in.
There is no intrinsic value in being "complete as a JS coder". JS isn't scripture.
No. Pointers have a coherent model and represent a fundamental low-level rule of how computers work.
'this' in javascript is just messy.
I personally almost never use it.
Ultimately I think it forces people to think about JS differently than what they might be typically used too.
I don't use "this". I use "new" for things like making an Array. I never modify a function's prototype.
I simply write functions at the top level, make all the signatures as explicit as I can, and keep everything as decoupled as I can.
If you need to create a new array and populate it with values, then using new Array( size ), and then looping through it to populate it will be faster than using a literal or new Array() and then looping through it.
It should be noted though, that the difference is negligible unless you're working on creating and pre-populating a lot of very large arrays.
This situation is rare to begin with, and even then in most cases it's not a big difference.
In perhaps the most common case, creating an empty array, a literal is generally faster than (or equivalent with) using the Array constructor (at least, in tests I have done).
I would go with the syntax you believe is cleaner unless you have a demonstrable perf bottleneck....speed shouldn't even be brought up until then (unless you are trying to decide between two truly equal options, then picking the faster one is reasonable, but that's not the case here)
That said, I jumped ship for CoffeeScript and recommend doing so to everyone. Everything tricky about 'this' is resolved quite elegantly.
Interesting read though.
thank you for =>
I can't count the # of times my tests were failing on new code I wrote and it took me one second to look at is and say, "Oh yeah... this" and just flip -> to =>. So easy.
is also a nice one
When "this" gives you a hard time, the Function.bind() method is often a good solution too.
var base = {
greet: function() { log('my name is ' + this.name); },
name: 'base'
}
var derived {
__proto__: base,
name: 'derived'
}
derived.greet();
If the greet function was bound at creation time to base, then the last line would print "my name is base" instead of the desired "my name is derived".var a = { b:function(){...}}; a.b() // a var c = false; (c || a.b)() // window
this context is always global
function value()
{
this.v = 32;
}
function twice( n )
{
n.v += n.v;
}
number = new value();
document.write( number.v + ' ' );
twice( number );
document.write( number.v );