5

Reading Principles of writing consistent, idiomatic JavaScript in the section titled "Faces of this" it suggests that aliasing this in JavaScript is "extremely bug prone".

I personally try to use _.bind() (or something similar) whenever possible but does anyone know why aliasing this is so error prone?

Darrell Brogdon
  • 6,843
  • 9
  • 47
  • 62
  • This behavior is by design. (pun intended) – SLaks Mar 06 '13 at 18:06
  • 1
    Could you explain a little more what you mean with "extremely bug prone"? I have never heard about it... can you give some examples? – Steve Mar 06 '13 at 18:07
  • Thanks SLaks - I might be wrong, but I don't see that as 'aliasing'? Or is it? I think of 'aliasing' more in terms of `var that = this;`, which doesn't really cause any problems... But maybe I am just misunderstanding the question. :) – Steve Mar 06 '13 at 18:14
  • @Steve I was quoting "Principles of writing consistent, idiomatic JavaScript" where it suggests you not alias this (`var that = this;`) but instead use something like Underscore's `_.bind()`. – Darrell Brogdon Mar 06 '13 at 18:19
  • 1
    Oh, sorry Darrell, I just realized that we are wondering about the same question. I just looked up the link you provided and read their statement: "As a last resort, create an alias to this using self as an Identifier. This is extremely bug prone and should be avoided whenever possible." --- I guess I am having the same question as you do: Why do they claim aliasing is error prone? – Steve Mar 06 '13 at 18:29

2 Answers2

7

There are four meanings this can take dependending on how it was invoked. Accordingly care must be taken to keep track of which this is being used, and I can think of this-prone problems in at least 3/4 of them.

Invoked as method

In obj.myFunc(), this binds to obj.

This one can be scary if myFunc is passed in a callback, as it will forget that it was once part of an object and be invoked standalone. See e.g. What does 'var that = this;' mean in JavaScript? for the usual workaround to this.

Invoked as standalone function

In plain myFunc(), this binds to global object.

Invoked as constructor

Invoked as new myFunc() (very different! All functions that are intended to be invoked with new should be capitalized, thereby looking like a pseudoclass). Creates a new object, binds it to this and (probably) returns that object.

Of course if you drop the new you will bind to the global object, which will likely clobber a lot of stuff and leave your program in a very broken state. The capitalization convention is very important, and lets this problem be picked up by JSLint (IIRC).

Invoked with apply (or call)

Invoked as myFunc.apply(obj, args), in which this binds to obj. Note this has security implications even, as any caller can swap out this with its own spoofed object.

Community
  • 1
  • 1
djechlin
  • 59,258
  • 35
  • 162
  • 290
4

this being aliases everywhere would be bug prone because it gets rather difficult (for the developer) to remember exactly what this is referring to in a given situation. This can easily lead to a developer using this believing it refers to one element, when in reality it is something totally different. For example:

$('#something').click ( function (e) {
    //this refers to the clicked element
    var _this = this;  //Tracking a reference to the clicked element `this`
    $.each(someArray, function(index, value) {
       //this refers to the current element being iterated in someArray
       $.ajax({
          url : 'some/path',
          success: function (res) {
             //this refers to the ajax request
             //_this still references the clicked element
          } 
       })
    })
})

Furthermore, if you need to access one this from within the scope of another this (for instance this clicked element from within the ajax call) you have to keep a reference to it somehow. I have marked this in the code.

Nick Mitchinson
  • 5,452
  • 1
  • 25
  • 31