You're not alone, every time I do this I feel like I'm going wrong somewhere. I know it's avoidable via binding/currying/proxying but often those solutions end up looking uglier and are harder to follow.
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
I just use 'this' as much as possible. It helps me keep track of which object/scope 'this' is referencing. Creating a second reference to the object/scope referenced by 'this' doesn't really change anything.
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').
Yes it does change things. You're not understanding that "this" is a keyword, not a variable reference, and as such, it is not treated the same in closures. The "this" KEYWORD is dynamically bound at runtime, not lexically scoped like every other variable. It is impossible to close over "this", yet it's what you usually want to do. That is why people use ugly work-arounds like "var me = this;". So "this" is a pitfall and language design flaw that traps many JavaScript programmers (even experienced ones) into thinking they're writing correct code that looks like it does one thing, which actually does a totally (and sometimes subtly) different thing.
The article is about 'this', not about creating closures.
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.
Douglas Crockford has said that he considers Lisp and Javascript to be similar languages. For that reason, I think it would help those confused/frustrated with 'this' to read the chapters of SICP that relate to the environment model, and to 'eval' and 'apply':
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.
> 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.
Except 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 simply made a pact with myself never to understand that monstrosity and so never to use it (except when forced to, e.g. by some library). My voyages in Javascript have been delightful ever since.
But in a manner of speaking, isn't your statement similar to a C++ programmer preferring to avoid understanding pointers?
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.
As Wittgenstein once said (and please, if anyone knows where, I've been trying to find it again for years): You can't have a clear picture of a stormy sea. "This" is an ill-defined concept (illustrated by the 3 categories and 5 subcategories of the OP) which, from what I've seen, often leads to unnecessary complexity.
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.
> "This" is an ill-defined concept (illustrated by the 3 categories and 5 subcategories of the OP)
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.
Of course I can use it if "the situation calls for it". But that's almost never the case.
"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.
It's only messy if you don't understand it. Just because a concept is difficult to grasp initially, doesn't mean it's messy. Using this properly can prove to be a very powerful and flexible tool in your JS skill set.
Ultimately I think it forces people to think about JS differently than what they might be typically used too.
This statement sounds very weird to someone who has written a lot of JavaScript. I'm skeptical that you could write JavaScript of any significant size without ever using "this". Do you also not use the "new" operator? Do you never modify a function's prototype?
I always think it's weird when I see people using "new" to make Array / Object. Unless you're using the ridiculously rare pre-initialization of an Array via "new Array(5)" it just feels clunky.
> Pre-allocating an array using new is measurably better for performance in some browsers.
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)
'this' can't easily be avoided when you get into OO/MVC patterns ala backbone.js, which have become a necessity for me when working on complex javascript apps.
That said, I jumped ship for CoffeeScript and recommend doing so to everyone. Everything tricky about 'this' is resolved quite elegantly.
My favorite is the Maybe-monad-esque ? syntax. It lets you write expressions like this: obj.a?.b?.c?() which will execute normally if all those properties exist, but return null instead of failing if they don't.
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.
I had trouble with this at first, but an easy thing to remember is that "this" is scoped dynamically; as many have noted before, you can easily create a lexical "that" or "self" reference from it, but the other way around is impossible. This dynamic scope is a bit strange when everything else has local scope but it can be quite powerful.
When "this" gives you a hard time, the Function.bind() method is often a good solution too.
I now feel fortunate to have started out with Actionscript 2. If there's anything that language drives home it's "this," due to the fact that you're usually writing code specific to an instance object on the stage. So the concept of var self = this; makes too much sense.
What is the benefit to having 'this' defined based on where a function is executed rather than where it is created? Is this mainly an artifact of the ability to assign a function created in one place to an object created elsewhere?
It allows you to inherit functions from a prototype and still have them execute against the current receiver. Consider:
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".
Now, I just put
at the top of very method and use 'that' everywhere in the function.