Cheetah
Cheetah

Reputation: 14399

Why would you create a variable with value this

I've seen this done alot in JavaScript and I do remember finding out why but I can't remember the answer.

I'm guessing it's something to do with scope and a function being called outside the "class" but why would one do this (preferably outlining an example):

function myClass ()
{
    var self = this;

    //...

    this.myArray = [];

    this.myFunc = function () { alert(self.myArray.length); };
}

Upvotes: 7

Views: 113

Answers (5)

Phrogz
Phrogz

Reputation: 303361

In order to latch onto the variable as part of a closure.

For example:

MyClass.prototype.doStuff = function(){
  this.foundItems = [];
  var self = this;
  this.myString.replace(/.../,function(){
    // `this` is actually the `window` inside this callback
    // so we need to use `self` to invoke another method on our instance object
    self.foundItems.push( self.doOtherStuff() );
  });
};

The specific example you wrote does not need a closure if you invoke the method in the expected way:

function Foo(){
  this.array = [];
  this.myFunc = function(){
    return this.array;
  }
}
var foo = new Foo;
foo.myFunc(); // []

However, it's possible to 'break' it like so:

var f2 = foo.myFunc;
f2(); // undefined, since `this` was the window

Your code using the closure, on the other hand, is safe against this sort of tomfoolery.

Upvotes: 5

Esailija
Esailija

Reputation: 140228

I don't think one really wants to do that:

  • Any time an instance is created, you also create a "copy" of the function. So 5 instances, will create 5 "copies" of the function.
  • That "copy" of a function is bound to an environment that is only relevant to that specific instance, so it cannot be used generically. That means an extending class will get a method that is only relevant for some instance of the parent class that is probably not even used.
  • Your indentation will get out of hand especially if you start nesting those inline functions
  • You'll have to hunt for functions inside other functions instead of just looking it up in the prototype definition

An alternative:

function MyClass() {
    this.myArray = [];
    this.myFunc = this.myFunc.bind(this); //The "blueprint" in the prototype is not affected, the instance gets its own bound version.
                                           //This means the one in prototype can be inherited or used generically anywhere else as well
}

MyClass.prototype = {

    myFunc: function() { //My func is neatly listed in the prototype and can use `this` normally
        alert(this.myArray.length);
    },

    constructor: MyClass
};


var myObj = new MyClass();

document.addEventListener( "click", myObj.myFunc ); //Will now work as you "expect" it to work

A few drawbacks:

  • Each bound function is a new function so per instance, 1 new function is still created every time.
  • Boilerplate in writing out all the .bind calls in the constructor, though can be mitigated with a helper like _.bindAll

Upvotes: 0

Matt
Matt

Reputation: 477

In addtion to some of the answers posted by other users, creating variable set to this allow you to reuse variables without accessing objects.

Similar to doing something like:

var myElement = document.getElementById('someElement');

And then accessing myElement if you need to rather than document.getElementById multiple times.

Setting that = this or self = this gives you access everywhere to "that" or "self" and prevents from re-loading some object.

Upvotes: 0

Nathan Hughes
Nathan Hughes

Reputation: 96424

If you create a function within another function, this for the inner function gets set to the global window object. If you create a variable saving the value of this, like

var that = this;

then you can use that to reference the outer function within the inner function.

Upvotes: 1

Sebas
Sebas

Reputation: 21542

"this" refers to the current "object". The power resides, when talking about javascript, into the fact that the "this" expression is evaluated context-wise, so for example if a method is executed in another object context, the "this" value will change respectively.

Upvotes: 2

Related Questions