题目
function Parent() {
this.a = 1;
this.b = [1, 2, this.a];
this.c = {
demo: 5
};
this.show = function() {
console.log(this.a, this.b, this.c.demo);
}
}
function Child() {
this.a = 2;
this.change = function() {
this.b.push(this.a);
this.a = this.b.length;
this.c.demo = this.a++;
}
}
Child.prototype = new Parent();
var parent = new Parent();
var child1 = new Child();
var child2 = new Child();
child1.a = 11;
child2.a = 12;
parent.show();
child1.show();
child2.show();
child1.change();
child2.change();
parent.show();
child1.show();
child2.show();
题目分析
(1) Child.prototype = new Parent();
Child.prototype作为Parent构造函数的一个实例,继承的常见用法。
通过继承实现了:
1、重写了Child的原型,让子类原型和子类函数之间断开了联系 2、子类原型是父类的实例
(2)var child1 = new Child();var child2 = new Child();
当两个对象为同一个构造函数的实例时,这两个实例是不共享该构造函数自身的属性的(即一个实例修改属性不会影响两一个实例的属性值),但是这两个实例会共享该构造函数原型上的属性(若属性值是引用类型,两个实例的该属性是指向同一个引用地址的) eg:
function Parent() {
this.a = 1;
this.b = [1, 2];
}
Parent.prototype = {
c: 5,
d: [1, 2, 3, 4, 5]
};
var parent1 = new Parent();
var parent2 = new Parent();
parent1.a = 3;
parent1.b.push(6);
parent1.c = 7;
parent1.d.push(8);
console.log(parent1);
console.log(parent2);
查看输出
现在进入正题,进行代码输出分析
(1) parent.show();
直接执行parent.show方法,输出1,[1,2,1],5
(2) child1.show();
child1实例是没有show方法的,会沿着原型链去查找,child1.proto == Child.prototype,Child.prototype.proto == Parent.prototype;所以child1会继承Parent的属性,又由于child1.a = 11。所以最终输出11,[1,2,1],5
(3) child2.show();
同上一题,输出12,[1,2,1],5
(4) child1.change();
this.b指向Child.prototype上的b数组,this.a指向child1的a属性,所以this.b和Child.prototype上的b数组都变为[1,2,1,11]; this.a = 4; this.c.demo = this.a++,即this.c.demo为4; 因为a++,所以此时this.a = 5;
(5) child2.change();
this.b指向Child.prototype上的b数组,this.a指向child2的a属性,所以this.b和Child.prototype上的b数组都变为[1,2,1,11,12]; 同上一题,this.a = 6;this.c.demo = 5;
经过(4)(5),Child.prototype.b = [1,2,1,11,12] Child.prototype.c.demo = 5;
(6) parent.show();
直接执行parent.show方法,输出1,[1,2,1],5
(7) child1.show();
经过(4)(5)的分析可知,输出5,[1,2,1,11,12],5
(8) child2.show();
经过(4)(5)的分析可知,输出6,[1,2,1,11,12],5