原型链输出题分析

314 阅读2分钟

题目

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);

查看输出

image.png

现在进入正题,进行代码输出分析

(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