Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Finally someone makes sense of JavaScript's this keyword (javascriptweblog.wordpress.com)
239 points by legomatic on April 23, 2011 | hide | past | favorite | 52 comments


I used to always run into trouble when trying to use 'this' inside a closure defined within an object's method.

Now, I just put

    var that = this;
at the top of very method and use 'that' everywhere in the function.


FWIW: that's exactly what ExtJS does:

    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.


same here, I use 'this' rarely. always start new function classes with var self = this; and never use 'this' again.


Aha! I also do "var self = this;" but feel really bad about it, like I'm missing something obvious about the language. I guess I'm not.


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.


I do the same thing with var me.

Another way is jQuery.proxy(), though that works best for calling a method with the correct context.


> Another way is jQuery.proxy()

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...

[1] http://documentcloud.github.com/underscore/#bindAll


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.


I do the same it's really expressive IMHO, it's strange at start but when you understand it it's awesome.


Spot on, I do the same (but I use $this as the variable name).


I use the $ sigil to differentiate between variables that are DOM elements and variables that are jQuery-wrapped DOM elements.


Same here.

     var _this = this;    //vanilla
     var $this = $(this); //jQuery
Though, I have encountered people who are really against the $var for stylistic reasons - so ymmv.


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':

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.


> 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.


JavaScript is incredibly different from Lisp, at least syntactically. Here are some legal JavaScript expressions:

  ++x+x++
  x >> 6 > y >> 6
  5 % 2 / 5 * 5 + 1


It's good that Crockford meant semantically, then.


Douglas Crockford does a good job of explaining this in JavaScript: The Good Parts. That book comes highly recommended.


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.


> But in a manner of speaking, isn't your statement similar to a C++ programmer preferring to avoid understanding pointers?

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.


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've written a lot of Javascript. It doesn't sound weird to me.

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.


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. This sometimes matters.


> 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.


Quite frankly, I personally fail to see the sense of this.

Interesting read though.


dear coffeescript,

thank you for =>


The fat arrow is the best piece of syntactic sugar cs offers.


I like the class and for comprehensions sugar very much as well.


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.


do (foo) ->

is also a nice one


this x1000.

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.


thanks, I have been using cs recently and didn't even know about it!


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".


I also found JavaScript Garden (posted on HN a few weeks ago) incredibly useful in un-confusing my understanding of JS.

http://bonsaiden.github.com/JavaScript-Garden/


nothing about context, then function called in expressions

var a = { b:function(){...}}; a.b() // a var c = false; (c || a.b)() // window

this context is always global


That's a needlessly complicated example. You could just write (function(){alert(this)})() -- and in fact, that's what was the very first example.


I still don't get it :-(


Sense could be an overstatement.


For the pragmatics, a simpler and not so cluttered example of the constructor, illustrating what 'this' does and how you can pass 'this' by argument:

  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 );


duh.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: