The current code assigns the object literal to the prototype of Person
. Instead, assign the function to the setFirstName
property of Person.prototype
:
Person.prototype.setFirstName = function(name) {
this.firstName = name;
console.log("My first name is: " + this.firstName);
}
Explanation
To understand the error, we must first understand how prototype
s work in Javascript. When an instance of an object is created using a function constructor the instance's prototype is assigned the prototype of the constructor function.
function MyObject(){}
var myObj = new MyObject();
console.log(myObj.__proto__ == MyObject.prototype); //logs true
In the provided code, an instance of Person
is created using the Person
constructor function. This causes person
to be assigned the prototype of Person
.
var person = new Person();
function Person() {
this.firstName = "";
}
console.log(person.__proto__); //logs Person{}
Then the object literal containing the setFirstName
function is assigned to the prototype of Person
.
Person.prototype = {
setFirstName: function(name) {
this.firstName = name;
console.log("My first name is: " + person.firstName);
}
}
At this point the Person
prototype is assigned to the object literal with the function, however the instance person
was created before the object literal was assigned to Person
's prototype. The instance person
's prototype does not refer to the object literal that was assigned to Person.prototype
after its instantiation.
console.log(person.__proto__ == Person.prototype); //logs false
While not recommended, we could have resolved or avoided this issue by creating the person
instance after the new prototype was assigned, such as:
$(document).ready( function() {
$("#firstName").on("change", getFirstName);
function Person() {
this.firstName = "";
}
Person.prototype = {
setFirstName: function(name) {
this.firstName = name;
console.log("My first name is: " + person.firstName);
}
}
var person = new Person();
function getFirstName() {
var firstName = $("#firstName").val();
person.setFirstName(firstName);
}
});
It is much better to assign the method to a property of Person.prototype
so that we do not create temporial coupling that dictates when an instance of Person
can be created.
This article does an excellent job of explaining prototype
and would be worth the read.