user3467349
user3467349

Reputation: 3191

Why is 'this' not taking on the correct scope

Okay, I know there are some thousand odd threads about the scope of this in Javascript (which makes one wonder if the language was well designed) - but I still can't explain 'this' one:

//works
function Cat() { 
 this.theCatName = "Mistigri"; 
 function meow() {alert(this.theCatName + " meow") }; 
 this.meow = meow }
}
var MyCat = new Cat()
MyCat.meow() 

//works
function Cat() { 
this.theCatName = "Mistigri"; 
function meow() {alert(this.theCatName + " meow") }; 
this.meow = function() { alert(this.theCatName + " meow") }
}
var MyCat = new Cat()
MyCat.meow() 

//works
function Cat() { 
this.theCatName = "Mistigri"; 
function meow() {alert(this.theCatName + " meow") }; 
Cat.prototype.meow = function() { alert(this.theCatName + " meow") }
}
var MyCat = new Cat()
MyCat.meow() 

//doesn't work
function Cat() { 
this.theCatName = "Mistigri"; 
function meow() {alert(this.theCatName + " meow") }; 
this.meow = function() { meow() } }
}
var MyCat = new Cat()
MyCat.meow() 

//doesn't work
function Cat() { 
this.theCatName = "Mistigri"; 
function meow() {alert(this.theCatName + " meow") }; 
Cat.prototype.meow = function() { meow() } }
}
var MyCat = new Cat()
MyCat.meow() 

Now my understanding is that in the later two cases the Cat.prototype.meow or this.meow are anonymous functions that happen to call meow(), which is an internal function of Cat() - but the context of this clearly refers to cat inside the function - What happens to it?

Here is a semi-canonical answer: See How to access the correct this / context inside a callback? But it only has the following to say about what the context of 'this' actually is:

this (aka "the context") is a special keyword inside each function and its value only depends on how the function was called, not how/when/where it was defined. It is not affected by lexical scope, like other variables.

Upvotes: 1

Views: 53

Answers (2)

Stefan van de Vooren
Stefan van de Vooren

Reputation: 2707

I hope this will help a bit: A variable declared within a function is not accessible outside of that function. A variable defined within a function is accessible to its nested functions.

function Cat() {

    // public var exist on the Cat instance: accesible from outside the Cat constructor
    this.theCatName = "Mistigri";

    // public function exist on the Cat instance
    // has access to all variables defined in the Cat constructor (_theCateName and _meow)
    // and all variables and methods defined on 'this'
    // this reference to a Cat Instance
    this.meow = function() {
        alert(this.theCatName);
        _meow();
    }

    // private var only accessible within the Cat constructor.
    var _theCateName = "_Mistigri"

    // private function only accessible within the Cat constructor.
    function _meow() {
        // _meow is defined as closure in the Cat constructor
        // In the function _meow 'this' is a reference to the scope from where the Cat function / constructor was applied (the window object in this case)

        alert(this.theCatName + " meow " + _theCateName); // outputs: undefined meow _Mistigri
    };

}
var MyCat = new Cat()
MyCat.meow()

alert (MyCat.theCatName)// outouts: Mistigri

Upvotes: 0

Guffa
Guffa

Reputation: 700182

When you call a method of an object it only works if you call it as a member of the object, if you get the reference to the function or call it as a regular function, the context isn't the object. It's only how you call the function that decides the context, the context isn't inherited so if you call a function from a method it's just a regular function call.

Example:

function Dog() {

  function bark() {}
  this.bark = bark;

  this.barkThrice() {
    bark(); // function call; context = window
    this.bark(); // method call; context = the object
    var b = this.bark;
    b(); // function call; context = window
  }

}

To call the function as a method of the object you need to use the call method (or bind or apply) to set the context of the call:

function Cat() { 
  this.theCatName = "Mistigri"; 
  function meow() { alert(this.theCatName + " meow"); } 
  this.meow = function() { meow.call(this); };
}
var MyCat = new Cat();
MyCat.meow();

Demo: http://jsfiddle.net/k6W9K/

Upvotes: 1

Related Questions