I declared the function:
function makePerson() {
this.first = 'John';
this.last = 'Oliver';
fullName = function(){
return this.first + this.last;
}
}
Did not instantiate it but called this function.
makePerson()
Now I am able to access first
, last
and fullName
in global access.
Can someone explain me why it happens.
Note: Rather than calling, I instantiated it and checked. It is not in global and is accessible within function/class/object scope.
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 :
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.anObject.f(a,b)
(method call syntax), this
is bound to anObject
.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());