1

I'm trying to understand how the this keyword works in this context.

function Person(name) {
    this.name = name;
    this.sayName = function() {
        alert('My name is ' + this.name);
    };
}


var p = new Person('Smith');
p.sayName();  // 'My name is Smith'

var q = p;

q.sayName();  // 'My name is Smith'

q = p.sayName;

q();  // 'My name is'   ???

Why is the last example not picking up 'Smith'?

Is it because q is simply pointing to a function (i.e. the object the method belongs to is not recognized in this context)? Since q is in the global space, this is global within the function (i.e. the caller of sayName() is the global space or window)?

Stephen
  • 1,983
  • 2
  • 24
  • 53
  • 2
    Because it all depends on how the function is called. In your last example, it has no context, so `this` is actually `window`. To overcome this problem, put `var that = this;` inside your `Person` function. Then, use `that` throughout to refer to the specific `Person` instances – Ian Jun 12 '13 at 19:54
  • 4
    `this` inside the a function is determined at invocation time depending on [how the function was invoked](http://stackoverflow.com/a/12371105/710446). `p.sayName()` and `q()` are different styles of invocation; the first is as a method of an object, the second as a "raw" function call. – apsillers Jun 12 '13 at 19:54
  • I thought q = p.sayName created context, because sayName() is part of p. So, assigning a variable to a method, even if it looks like it is part of an object, is just creating a raw function call. – Stephen Jun 12 '13 at 20:48

2 Answers2

2

It's because this refers to the context that the function is called from. When you do p.sayName() the context is p. If you just call a function without context, it will default to the global context (usually window) or undefined in strict mode.

If you want to make it work the way you were expecting you can bind this to p, so that q():

q = p.sayName.bind(p);

q(); // My name is Smith
Paul
  • 130,653
  • 24
  • 259
  • 248
1

Piggybacking on what @Paulpro said, you can create a reference to the Person() context by adding var that = this; inside the class. That way you could call that.name from inside the function.

function Person(name) 
{
    var that = this;

    this.name = name;
    this.sayName = function() 
    {
        alert('My name is ' + that.name);
    };
}


var p = new Person('Smith');
p.sayName();  // 'My name is Smith'

var q = p;

q.sayName();  // 'My name is Smith'

q = p.sayName;

q();  // 'My name is Smith'


View jsFiddle demo

Code Maverick
  • 19,231
  • 10
  • 57
  • 111