3

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.

Unihedron
  • 10,902
  • 13
  • 62
  • 72
Sumesh Kuttan
  • 1,333
  • 1
  • 17
  • 40
  • you should go through this http://www.smashingmagazine.com/2009/08/01/what-you-need-to-know-about-javascript-scope/ – Abdul Jabbar Aug 11 '14 at 09:06
  • 1
    Because `fullName`, as you declared it, is a global function. – MaxArt Aug 11 '14 at 09:07
  • 2
    in your case `this === window` so, `this.first = 'John'` equals to `window.first = 'John'` and equals to `var first = 'John'`. That is because you call your class as function. Use it as constructor `var person = new makePerson()`, and after this you can access to `person.first`. Also, change `fullName` to `this.fullName` – Umidbek Aug 11 '14 at 09:08
  • @UmidbekKarimov thanks. ur replu and the answer below explained the concept pretty well. – Sumesh Kuttan Aug 11 '14 at 09:51
  • Maybe the following answer will help: http://stackoverflow.com/questions/16063394/prototypical-inheritance-writing-up/16063711#16063711 – HMR Aug 11 '14 at 11:38
  • @HMR Thanks for that wonderful link. That explains a lot. – Sumesh Kuttan Aug 11 '14 at 18:17

1 Answers1

3

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 :

  1. 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.
  2. In anObject.f(a,b) (method call syntax), this is bound to anObject.
  3. 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());
Valentin Waeselynck
  • 5,950
  • 26
  • 43