在使用javascript原型的过程中出现了令我困惑的一个情况:新建一个名为Person的类,并定义了原型对象如下:
运行结果预想的应该是 sam 27 ['a','b','c','d'],看下运行结果:
本来我预想的执行结果应该是[‘a’,'b','c','d','e'] ,[‘a’,'b','c','d','e'],solo,solo
/**
* Created by Sam on 2015/11/9.
*/
function Person(){};
Person.prototype={
constructor:Person,//强制指向构造函数
name:'',
age:0,
hobby:['a','b','c'],
run:function(){
return this.name+" is "+this.age+" years old";
}
}
然后实例化了这个类
var person = new Person();
person.name = 'sam';
person.age = 27;
person.hobby.push('d');
console.log(person.name);
console.log(person.age);
console.log(person.hobby);
运行结果预想的应该是 sam 27 ['a','b','c','d'],看下运行结果:
运行结果和预想的一致;
然后在使用该类创建一个对象,并对其进行相关操作并打印出信息:
var person = new Person();
person.name = 'sam';
person.age = 27;
person.hobby.push('d');
// console.log(person.name);
// console.log(person.age);
// console.log(person.hobby);
var person1 = new Person();
person1.name="solo";
person1.hobby.push('e');
console.log(person1.hobby);
console.log(person.hobby);
console.log(person.name);
console.log(person1.name);
本来我预想的执行结果应该是[‘a’,'b','c','d','e'] ,[‘a’,'b','c','d','e'],solo,solo
但是运行结果跟预想的不一致,为何hobby这个属性共享了但是name这个属性没有共享,对person1进行操作的时候不是应该修改了原先对象中的值么?
后来调试发现原型中的hobby属性确实是变了,但是name和age属性是没有被改变的
再回头看代码中
person.name = 'sam';
person1.name="solo";
这两句赋值语句其实是为实例化好的对象添加了一个名为name的属性并为其各自赋值,并未触及到他们的原型对象,所谓的就近原则,而
person1.hobby.push('e');
这句并未进行赋值而是直接操作其中的对象,所以会先在实例属性中找hobby这个属性,发现实例属性中并没有名为hobby的,然后就去原型中找,最后找到了并对其进行了改变,为了验证这个想法是否正确,对hobby进行个赋值操作看下会有什么改变:
var person = new Person();
person.name = 'sam';
person.age = 27;
<span style="color:#FF0000;"> person.hobby=['h','i'];</span>
// console.log(person.name);
// console.log(person.age);
// console.log(person.hobby);
var person1 = new Person();
person1.name="solo";
person1.hobby.push('e');
console.log(person1.hobby);
console.log(person.hobby);
console.log(person.name);
console.log(person1.name);
预想的结果应该是person打印出的hobby是[‘h’,'i'],因为使用的是实例属性而非原型属性,而person1应该打印出[‘a’,'b','c','e'],看下结果
然后调试看下,person下面应该有了一个名为hobby的属性,而person1肯定是没有的
结论:在使用原型进行实例化时,实例化出的对象采用就近原则进行属性查找,如果实例属性中有这个属性则使用实例属性如果没有则使用原型属性