These are the normal semantics of the this
keyword in a function. this
may be evaluated in several ways, depending on how you call the function. Let's say we have the function f
which body contains the this
keyword :
- In
f(a,b)
(standard function call syntax) this
is bound to the global JavaScript Object
, which means that if you add properties to this
in the function body, you actually add them to global scope.
- In
anObject.f(a,b)
(method call syntax), this
is bound to anObject
.
- In
new f(a,b)
(constructor call syntax), this
is bound to the object being constructed.
this
can be a source of confusion, and as soon as a function body contains this
, the function stops being first-class. For that reason, I recommend you to avoid using this
as much as you can, as does Douglas Crockford.
If you want to make a factory function (which I strongly recommend for the reason above), you may do it that way :
function makePerson() {
var person = {
first: 'John',
last: 'Oliver'
};
person.fullName = function(){
return person.first + person.last;
};
return person;
}
If you still want to make a constructor, convention dictates that the name be capitalized :
function Person() {
this.first = 'John';
this.last = 'Oliver';
this.fullName = function(){
return this.first + this.last;
};
}
Finally, there can be good reasons to use the this
keyword, and that is prototypical inheritance. However, I find the constructor syntax to be misleading in that regard. Fortunately, now we have Object.create
:
var personPrototype = {
fullName: function () {
return this.first + this.last;
}
};
function makePerson(first,last) {
var person = Object.create(personPrototype);
person.first = first;
person.last = last;
return person;
}
As a last warning, here is an example of how using this
can lead to unanticipated constraints and confusion :
var cn = makePerson("Chuck","Norris");
// works fine
console.log(cn.fullName());
// does not work, fullName is not a first-class function. You cannot detach it.
var fullName = cn.fullName;
console.log(fullName());