The problem is that when you do:
return { ...
You are creating a new object, separate from the object that the new keyword previously created (the one you assigned two properties to). You might notice that jeff instanceof Person is false and jeff.constructor === Object.
See this example:
function Person(name, age) {
this.name = name;
this.age = age;
return {
theObjectThatNewCreated: this
}
}
var jeff = new Person('jeff', 28);
console.log( JSON.stringify( jeff ) );
// {"theObjectThatNewCreated":{"name":"jeff","age":28}}
console.log( jeff.constructor );
// Object
console.log( jeff.theObjectThatNewCreated.constructor );
// Person
You could fix it by assigning the name and age properties to the object you return instead of to this:
function Person(name, age) {
return {
name: name,
age: age,
ageUp: function ageUp() {
this.age++;
},
printInfo: function printInfo() {
console.log(this.name + " is " + this.age + " years old");
},
changeName: function changeName(newName) {
this.name = newName;
}
}
}
var jeff = new Person('jeff', 28);
jeff.printInfo();
But then Person isn't really a constructor, it is just an object factory and there is no point calling it with new. The objects it returns are not instances of Person, they are plain old Objects. There is a better way.
Am I combining two design patterns that I shouldn't be? What would be the best way to go about this?
I would say you are combining the revealing module pattern with a normal JavaScript constructor.
Instead of returning a new object you can just use this all the way through, to assign those functions as properties of the Person object instead of a new object:
function Person(name, age) {
this.name = name;
this.age = age;
this.ageUp = function ageUp() {
this.age++;
};
this.printInfo = function printInfo() {
console.log(this.name + " is " + this.age + " years old");
};
this.changeName = function changeName(newName) {
this.name = newName;
};
}
var jeff = new Person('jeff', 28);
jeff.printInfo();
But since those functions don't use any closed over variables from the constructor, they really should be added to the prototype of the constructor instead:
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.ageUp = function ageUp() {
this.age++;
};
Person.prototype.printInfo = function printInfo() {
console.log(this.name + " is " + this.age + " years old");
};
Person.prototype.changeName = function changeName(newName) {
this.name = newName;
};
var jeff = new Person('jeff', 28);
jeff.printInfo();