0

I'm confused as to what the problem is with context in a JS constructor. Within the ctor I have a function declared. Before the call to that function this is set to the context of the ctor. Inside the function the value of this is set to window. I don't understand why. In the HTML the ctor is called with 'new'.

function MyCtor() {
    var myFunc = function() {
         debugger; // #2
         // code for myFunc
     }

     debugger;  // #1
     myFunc();
     debugger;  // #3
}

At debugger #1, this is set to MyCtor. At #2 this is window. And at #3 it is back to MyCtor.

I'm sure I'm missing something basic here, but I've read a lot on scope and context; obviously not enough.

Ian
  • 46,701
  • 13
  • 94
  • 107
Les
  • 407
  • 1
  • 6
  • 17
  • 2
    Read about functions and scope here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope – Ian Oct 10 '13 at 21:18
  • …and about the [`this` keyword ("context") here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this). It should never have been set to `MyCtor`, unless you're calling the constructor in weird ways. – Bergi Oct 10 '13 at 21:29
  • @Bergi when we call MyCtor with new, what will the 'this' be displayed inside the body? – grape_mao Oct 10 '13 at 21:35
  • @grape_mao: The new instance (an object inheriting from `MyCtor.prototype`). https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this#As_a_constructor – Bergi Oct 10 '13 at 21:36
  • @Bergi sure, but in the console it shows somwthing like 'MyCtor{}'. Maybe that's why OP says this is set to MyCtor. – grape_mao Oct 10 '13 at 21:43
  • @grape_mao: Yeah, the console might display it as "object constructed by MyCtor". Yet when expanding its properties you should notice that it's not the `MyCtor` function :) – Bergi Oct 10 '13 at 22:13

1 Answers1

2

The this object is one of the most annoyingly hard-to-understand concepts in Javascript. And that's quite a contest to win... First off, you have to understand that it will be specific to each function you call - the context in which you call myFunc won't set it how you want it. Here's one way you can do it:

function MyCtor() {
    this.myFunc = function() {
         debugger; // #2
         // code for myFunc
     }

     debugger;  // #1
     this.myFunc();
     debugger;  // #3
}

Generally, there are only a few situations in which you can rely upon a function's this to be a particular value. All of them to my knowledge:

objectToBeThis.aFunction = function() { ... } // declare this function as
// an object property at any time - 
objectToBeThis.aFunction();

Or, not used as often is:

aFunction.call(objectToBeThis, extraArgument1, extraArgument2);

When a named, but not "owned" function (ie, var functionName = function(), or function functionName()) is called, then it will have window as its this argument. This part I'm less sure of as a certainty, but I just wouldn't use this inside such a method.

As in the case of your code, there's also "new MyCtor" - in which a new object is created to be returned, and that object is set to this inside of the constructor method.

Katana314
  • 7,879
  • 2
  • 25
  • 34
  • Still a bit confused here. Does this mean that via hoisting, all 'var' declarations really belong to 'window'? I would think that that would lead to name collisions. If `myFunc` is declared within the constructor using 'var', why isn't it bound to `MyCtor`? – Les Oct 10 '13 at 22:51
  • Found additional info in (http://stackoverflow.com/questions/8670877/this-value-in-javascript-anonymous-function) – Les Oct 10 '13 at 23:35
  • Anything that belongs to 'window' is a global. Any function arguments, or variables declared inside of a function, are local variables accessible to that function, as well as any functions declared inside that function (closures). `var`s don't really "belong" to any object, and as such, you don't use the dot syntax for them. This also means you can't access a `var` outside of the function it was declared in. Hope that helps; it's definitely confusing. – Katana314 Oct 11 '13 at 01:02