Function variable added to global scope

I have declared a function:

function makePerson() {
    this.first = 'John';
    this.last = 'Oliver';
    fullName = function(){
        return this.first + this.last;
    }
}

      

Didn't instantiate but did call this function.

makePerson()

      

I can now access first

, last

and fullName

globally.

Can someone explain to me why this is happening.

Note. Instead of calling it, I created it and tested it. It is not global and is available within the scope of functions / class / object.

+3


source to share


1 answer


This is the normal semantics of a keyword this

in a function. this

can be evaluated in several ways, depending on how you call this function. Let's say we have a function f

where the body contains a keyword this

:

  • B f(a,b)

    (standard function syntax) is this

    tied to global JavaScript Object

    , which means that if you add in properties in this

    the body of a function, you will actually add them to the global scope.
  • The anObject.f(a,b)

    (method call syntax) is this

    bound to anObject

    .
  • B new f(a,b)

    (constructor call syntax) is this

    bound to the object being constructed.

this

can be a source of confusion, and once the function body contains this

, the function is no longer first-class. For this reason, I recommend that you do not use this

as much as you can, like Douglas Crockford .

If you want to make a factory function (which I highly recommend for the above reason), you can do it like this:

function makePerson() {
    var person = {
        first: 'John',
        last: 'Oliver'
    };
    person.fullName = function(){
        return person.first + person.last;
    };
    return person;
}

      

If you still want to create a constructor, the convention requires the name to be capitalized:



function Person() {
    this.first = 'John';
    this.last = 'Oliver';
    this.fullName = function(){
        return this.first + this.last;
    };
}

      

Finally, there may be good reasons for using a keyword this

, and that is prototypical inheritance. However, I find the constructor syntax to be misleading. Fortunately, we now 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 final warning, here's an example of how usage this

can lead to unexpected restrictions 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());

      

+3


source







All Articles