In JavaScript, this
is typically whatever comes before the .
in the function call. So the fact that you said dude.fullName()
is what caused this
in fullName()
to be set to dude
1.
In the second version in your question, you're not calling it the same way. You're calling personFullName()
without anything in front of it (which is correct, since it's no longer attached to a Person object). That means that this
ends up defaulting to the same value as window
. Since window
has no first
or last
properties set on it, this.first
and this.last
are undefined
.
To fix this, you can make your person be an argument to the personFullName() function:
function personFullName(person) {
return person.first + ' ' + person.last;
}
and then call it like
…
this.fullName = personFullName(this);
1: Note that the method has to be a property on the object for the this
binding to work. You can't just call object.someMethod()
and get have this
set to object
in someMethod
. In your code, the following would not work:
function Person(first, last) {
this.first = first;
this.last = last;
this.fullName = this.personFullName();
}
Uncaught TypeError: this.personFullName is not a function
Neither would this:
function personFullName() {
return this.first + ' ' + this.last;
}
function Person(first, last) {
this.first = first;
this.last = last;
}
var dude = new Person("Michael", "Jackson");
alert(dude.personFullName());
Uncaught TypeError: dude.personFullName is not a function
You can get around this restriction in any situation with the apply
helper method: this.fullName = personFullName.apply(this)
does what you expect the second version of your code to do and you can also call personFullName.apply(dude)
at any point and get "Michael Jackson"
back.