M1Reeder
M1Reeder

Reputation: 712

Can't add method prototype to JavaScript object

I was messing around with Javascript prototypes, and I don't understand why this works:

function User(un) {
    this.username = un;
}

User.prototype.method_name = function() {
    return this.username;
};

var user = new User("Michael");

console.log(user.method_name());

But this doesn't:

function User(un) {
    this.username = un;
    return{
        getUsername: function (){
            return username;
        },
        setUsername: function(username) {
            username = un;
        }
    };
}

User.prototype.method_name = function() {
    return this.username;
};

var user = new User("Michael");    
console.log(user.method_name());

Why does adding the "return" statement throw Object #<Object> has no method 'method_name'?

Upvotes: 1

Views: 954

Answers (2)

Zach
Zach

Reputation: 7930

Returning an object circumvents the usual return value of a constructor, which is the this variable. Instead of returning this, you're returning some other object, and that object doesn't have a username property or a method_name method. This is roughly what happens at each point in the code:

function User(un) {
    this.username = un; // puts username on the 'this' object

    // returns an entirely different, unrelated object that doesn't use User's prototype
    return{
        getUsername: function (){
            return un;
        },
        setUsername: function(username) {
            un = username;
        }
    };
}

// sets method_name on the prototype of the 'this' object for User
User.prototype.method_name = function() {
    return this.username;
};

var user = new User("Michael"); // passes a new User.prototype as the implicit 'this' in the User function   
console.log(user.method_name());

Instead, try this:

function User(un) {
    this.username = un;
    this.getUsername = function (){
        return un;
    };
    this.setUsername = function(username) {
        un = username;
    };
}
User.prototype.method_name = function() {
    return this.username;
};

Upvotes: 3

RobG
RobG

Reputation: 147363

Because in the second example, the object you return isn't a new "User" instance, but a plain Object instance.

When you use the new key word with a constructor, the object returned by default inherits from the constructor's prototype, so you have an inheritance chain like:

user -> User.prototype -> Object.prototype -> null

If you return some other object, it doesn't inherit from the constructor and you have an inheritance chain like:

user -> Object.prototype -> null

Upvotes: 4

Related Questions