1

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.

Community
  • 1
  • 1
user3467349
  • 3,043
  • 4
  • 34
  • 61

2 Answers2

1

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/

Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • Edit: I understand how to fix it, but I don't understand what's actually happening to the context of 'this'. meow() is a function of Cat(), being called by another function of Cat() both of which have this.theCatName in their context? So what is 'this' trying to reference when it cannot find theCatName ? – user3467349 Jun 22 '14 at 19:15
  • @user3467349: The function `meow` is not a member of the object, it's a function inside the `Cat` function. Javascript doesn't have a class scope, where everything in it is part of the class. – Guffa Jun 22 '14 at 19:30
0

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
Stefan van de Vooren
  • 2,524
  • 22
  • 19