巴扎黑2017-04-10 17:14:32
默认情况下,实例的原型就是它的构造函数的prototype
所引用的对象。也就是说
person1.__proto__ === person2.__proto__ === Person.prototype
这3者是同一个对象。
巴扎黑2017-04-10 17:14:32
Person作为一个类,会有自己的一些公有属性和私有属性,你可以将prototype理解成这个类的公有属性,既然是公有的,那就是别人也能使用并且改变的。person1和person2都具有Person这个类的公有方法和属性,当person1改变了公有属性,另一个也实例person2的属性值也改变了。从内存的角度来讲,公有属性在内存里的就只有一个地址,前者(person1)操作完了,后者(person2)去读取的时候自然就是刚刚改完的。
为了避免这种情况,就应该把不想被共享的属性私有化,如下代码:
function Person(friends) {
if ( friends )
this.friends = friends;
}
Person.prototype = {
constructor: Person,
name: 'Nicholas',
age: '29',
job: 'Software Engineer',
friends: ['Shelby', 'Counrt'],
sayName: function() {
alert(this.name);
}
};
var person1 = new Person(['Van']);
var person2 = new Person();
person1.friends.push("Van");
console.log(person1.friends);//['Van', 'Van']
console.log(person2.friends);//['Shelby', 'Counrt']
补充一句,属性的查找是基于原型链的,person1有自己的私有属性friends
也有公有属性friends
,取值的时候先查找有没有私有属性,再去查找公有属性,如果公有属性也没有,就继续往上找(Object构造函数),直到顶端。
书上的Demo中friends是数组,也就是引用类型的对象,push是这个数组具有的一个方法,所以调用push方法的时候并不会改变这个对象的内存地址。如果你是直接赋值
,实际上是定义了私有属性:
function Person() {
}
Person.prototype = {
constructor: Person,
name: 'Nicholas',
age: '29',
job: 'Software Engineer',
friends: ['Shelby', 'Counrt'],
sayName: function() {
alert(this.name);
}
};
var person1 = new Person(['Van']);
var person2 = new Person();
person1.friends = "Van";
console.log(person1);// Person {friends: 'Van'}
console.log(person2);// Person {}
书上的demo,因为是person1.friends.push,所以friends一定是具有push方法的,而公有属性'friends'恰恰具有这个方法,也即是先执行了查找操作。
对于上面的第二个demo,由于是赋值操作,改变了内存空间,Javascript认为这是声明私有变量操作,原有的公有属性不会改变