JavaScript中,不是在实例中修改prototype属性会在该实例中隐藏类的prototype属性,而其他实例不受影响吗?
function Person(){
}
Person.prototype = {
name : "Nicholas",
age : 29,
friends : ["Shelby", "Court"]
};
var person1 = new Person();
var person2 = new Person();
person1.friends.push("Van");
alert(person1.friends); //"Shelby,Court,Van"
alert(person2.friends); //"Shelby,Court,Van"
person1.name = 'tom';
alert(person1.name); //tom
alert(person2.name); //Nicholas
请看代码,
person1.friends.push("Van");给friends数组添加了元素“van”。person1.friends、person2.friends都输出了"Shelby,Court,Van"。
(是不是说明prototype里的数组也改变了?)
person1.name = 'tom';在person1中将name属性改成了‘tom’。
person1.name输出了‘tom’,person2.name则输出了‘Nicholas’。
说明prototype里的name没有改变.
请问这该如何解释?
谢谢
取对象属性值的时候,优先取对象自己的属性值,如果自己没有对应属性,就取__proto__
属性下的对应属性(即所拓展对象的属性或构造函数的prototype
属性啦),如果还是没有,才返回undefined
。
说完取,就说修改啦。通过对象.
的赋值修改只能修改对象下的直接属性,是永远不会修改__proto__
属性下的对应属性的。比如说,person1.name="tom";
这一步实际的操作是,直接将"tom"赋值给person1.name
属性,而不是person1.__proto__.name;
那么person1.friends.push("Van");
为什么能修改成功呢?注意啦,person1.friends.push("Van");
不是赋值修改,它是先取出person1.__proto__.friends
对象,然后对其进行操作的,所以能够修改成功。如果person1.friends=["jay","jane"];
,你就会发现person2.friends
的值还是"Shelby", "Court"
。
function Person(){
}
Person.prototype = {//对应的是实例化对象person1,person2的__proto__属性
name : "Nicholas",
age : 29,
friends : ["Shelby", "Court"]
};
var person1 = new Person();
var person2 = new Person();
person1.friends.push("Van");
alert(person1.friends); //"Shelby,Court,Van"
alert(person2.friends); //"Shelby,Court,Van"
person1.name = 'tom';//person1.__proto__.name其实没有改变
//person1.__proto__.name和person2.__proto__.name 指向的是同个值
alert(person1.name); //tom
alert(person2.name); //Nicholas
person1.__proto__.age = 20;//直接修改__proto__对象属性
alert(person1.age); //20
alert(person2.age); //20
引用的问题
赋值符号(=)修改的是name,push方法修改的是friends的引用,两者修改的东西不一样
至于new了两个对象,它们初始的name和friends引用相同的对象这些,你自己慢慢理解
其实这个问题,我们还是可以先看看文档是怎么描述prototype
这个东西的:
注意被选中的部分
原因是可能其他朋友已经提到了,prototype
上的属性是在所有实例对象里共享的,除非你改变它。
//这个就属于改变,因为变量name指向的内容已经变了
person1.name = 'tom';
//这个就不属于改变,因为friends指向的内容仍然是之前那个数组
person1.friends.push("Van");
要修正你的问题也很简单,只要把friends
从prototype
上移到构造函数里,让他成为一个实例变量就好了:
function Person() {
this.friends = ['Shelby', 'Court'];
}
Person.prototype = {name: 'Nicholas', age: 29};
var person1 = new Person();
var person2 = new Person();
person1.friends.push('Van');
console.log(person1.friends); //[ 'Shelby', 'Court', 'Van' ]
console.log(person2.friends); //[ 'Shelby', 'Court' ]