简体   繁体   中英

Setting prototype's object's field changes all instances

JSFiddle

function Person(first, last, age, eye) {
    this.firstName = first;
    this.lastName = last;
    this.age = age;
    this.eyeColor = eye;
}
Person.prototype = {
    nationality : {
        type : ""
    },
    changeNationality:function(n){
        this.nationality.type = n;
    }
};

var myFather = new Person("John", "Doe", 50, "blue");

var myMother = new Person("Jane", "Doe", 50, "blue");

myMother.changeNationality("English");
myFather.changeNationality("German");

document.getElementById("demo").innerHTML =
"My father is " + myFather.nationality.type + "<br/> My mother is " + myMother.nationality.type;

When i change the nationality of myFather it changes myMother's nationality too. What can be the reason?

Because you're defining nationality at the prototype level instead of the Person instance, thats the very reason for the prototype ! The idea is to be shared among all the class instances, otherwise every instance would have its own definition of every method, using much more memory and potentially diverging behaviors.

Try moving nationality to the constructor function:

function Person(first, last, age, eye) {
    this.firstName = first;
    this.lastName = last;
    this.age = age;
    this.eyeColor = eye;
    this.nationality = { type: "" };
}

Since the prototype is shared along every instance of your object definition, you should do something like this:

 function Person(first, last, age, eye) { this.firstName = first; this.lastName = last; this.age = age; this.eyeColor = eye; this.nationality = { type : "" }; } Person.prototype = { changeNationality:function(n){ this.nationality.type = n; } }; var myFather = new Person("John", "Doe", 50, "blue"); var myMother = new Person("Jane", "Doe", 50, "blue"); myMother.changeNationality("English"); myFather.changeNationality("German"); document.getElementById("demo").innerHTML = "My father is " + myFather.nationality.type + "<br/> My mother is " + myMother.nationality.type; 
 <p id="demo"></p> 

To prevent this assign properties to the prototype using one level dot and string assignments.

 function Person(first, last, age, eye) { this.firstName = first; this.lastName = last; this.age = age; this.eyeColor = eye; this.changeNationality = function(n){ this.nationalityType = n } } Person.prototype.nationalityType = 'default'; var myFather = new Person("John", "Doe", 50, "blue"); var myMother = new Person("Jane", "Doe", 50, "blue"); myMother.changeNationality("English"); myFather.changeNationality("German"); document.getElementById("demo").innerHTML = "My father is " + myFather.nationalityType + "<br/> My mother is " + myMother.nationalityType; 
 <p id="demo"></p> 

changing

changeNationality:function(n){
        this.nationality.type = n;
    }

to

changeNationality:function(n){
        this.nationality = {type : n};
    }

should also work because setting a property will create a new one on the object. But in case of this.nationality.type = n;

this.nationality is a get and doing .type on that is set hence it will assign the value from where it get it ie from prototype. Hence you are getting the behaviour. I have updated the fiddle you can check it here

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM