kentz
kentz

Reputation: 47

Why JavaScript methods inside a function used as an object constructor need to be assigned to a property of the object?

I'm studying JavaScript and I saw this example from w3schools.com (yes, I know about w3fools):

<script>
function person(firstname,lastname,age,eyecolor)
{
this.firstname=firstname;
this.lastname=lastname;
this.age=age;
this.eyecolor=eyecolor;

this.changeName=changeName; 
function changeName(name)
{
this.lastname=name;
}

}
myMother=new person("Sally","Rally",48,"green");
myMother.changeName("Doe");
document.write(myMother.lastname);
</script>

When I tried to remove the this.changeName=changeName; part, the function no longer functioned. My question is why is that part needed? There was no explanation about it, it was just there.

Upvotes: 1

Views: 81

Answers (3)

apsillers
apsillers

Reputation: 115970

We might rewrite the code to make it clearer:

function person(firstname,lastname,age,eyecolor) {
    ...
    var myChangeNameFunc = function(name) {
        this.lastname = name;
    }
    this.changeName = myChangeNameFunc; 
}

Or even shorter, using an anonymous function:

function person(firstname,lastname,age,eyecolor) {
    ...
    this.changeName = function(name) {
        this.lastname = name;
    }
}

The new keyword creates a new object, allows you to modify that object through the this identifier, and then returns the new object. By doing this.changeName=changeName, you assign the changeName function to the changeName property of the newly-created object in this.

That's a little confusing, so in my first example above, I did this.changeName = myChangeNameFunc to make it clear that the constructor-scope variable myChangeNameFunc and the object property this.changeName are different variables (although in this case they ultimately refer to the same object).

Without that assignment, the myChangeNameFunc function is never attached to the newly-created object -- it's just a function defined within the person constructor function.


Some bonus background:

  • function(name) { this.lastname = name; } is a function expression.

  • var myNameChangeFunc = function() { } assigns that function expression to a local variable in the constructor. (Variables in JS are function-scoped, so myNameChangeFunc is not accessible outside of the constructor function.)

  • function changeName() { } is a function definition. This is basically the same as var changeName = function() { }, except that the assignment is "hoisted" to the top of the containing function (so imagine it as the first line of the constructor function).

Thus, the function is originally stored in a constructor-local variable. By storing it in a property of this, it become a method of the constructed object, instead of just a function that is local to the constructor.

Upvotes: 4

plalx
plalx

Reputation: 43728

Let's consider this example:

var object = {};

function someFn() {}

Here you can clearly see that object doesn't have a someFn member. If you want object to have the someFn function we need to do:

object.someFn = someFn;

Well in your example you can imagine that this is object in the previous example. changeName is just a private variable declared in the constructor's function scope so you need to assign it to this if you want it to be a public function on your instanciated object.

Upvotes: 0

Jon
Jon

Reputation: 437534

Seen alone, the function changeName is local to the person constructor scope and therefore not visible outside that scope -- it's somewhat like a private method.

If you want to that method to be callable from the outside world then you have to create a property on the newly created person and set its value to that function. That way it can be accessed as myMother.changeName (just like any other property) and invoked.

Upvotes: 3

Related Questions