首页 > 看JavaScript高级程序设计里的6.3.3组合继承代码的疑问?

看JavaScript高级程序设计里的6.3.3组合继承代码的疑问?

1.代码如下:

function SuperType(name){
            this.name =name;
            this.colors = ["red","blue","green"];
            this.sex = "man"
        }
        SuperType.prototype.sayName = function(){
            alert(this.name);
        };
        function SubType(name,age){
            //1.继承属性
            SuperType.call(this,name);
            this.age = age ;

        }
        //2.继承方法
        SubType.prototype = new SuperType();
        SubType.prototype.constructor = SubType;
        SubType.prototype.sayAge = function(){
            alert(this.age);
        };
        var instance1 = new SubType("Nichloas",29);
        instance1.colors.push("black");
        alert(instance1.colors);
        alert(instance1.sex);
        instance1.sayName();
        instance1.sayAge();

        var instance2 = new SubType("Greg",27);
        alert(instance2.colors);
        instance2.sayName();
        instance2.sayAge();

2书上这句SubType.prototype = new SuperType();SubType.prototype.constructor = SubType代码的疑问,我是这样想的:这个SuperType的实例赋值给SubType的原型,不是意味着SubType的原型对象中constructor属性指向SuperType,那么他设SubType.prototype.constructor = SubType,不是把constructor重新指向SubType,这样,SuperType的方法还能被继承吗?SubType.prototype.constructor = SubType这句什么意思?


SubType.prototype = new SuperType();这句就已经把SuperType的方法继承给SubType了;SubType.prototype.constructor = SubType;只是覆盖了SubType.prototype的constructor属性,怎么会影响SubType.prototype里的其他方法呢?


个人对于这段代码的理解是SubType的原型继承了SuperType,是为了继承SuperType的原型方法,但实例化的时候,连带constructor属性一起改变了。constructor本身是要指向prototype属性所在的函数,为了能够确定对象原本的指向,也就是SubType,要将这个属性指回原本的构造函数,SuperType的方法依然会被继承。


这样,使用了new,意味着子类的原型链是一个崭新的原型链,而跟父类区分开来,但是构造函数依旧使用父类的构造函数,所以要重新指向子类自己专有的构造函数,这是我自己的理解,有错误请指正:)


SubType.prototype.constructor 指向的原型本来就是 SubType ,别被迷惑了!
SubType.prototype = new SuperType(); SubType继承SuperType的原型


constructor本来就是构造函数的意思,子类当然要有自己的构造函数啊,正是因为SubType.prototype = new SuperType()有副作用,使SubType.prototype.constructor指向了SuperType,所有才需要SubType.prototype.constructor = SubType来纠正这个副作用。


SubType.prototype = new SuperType();

这个是想让SubType继承SuperType的属性跟方法。但是这样SubType.prototype.constructor会被SuperType.prototype.constructor,也就是SuperType给替换掉,就会将原先SubType的构造函数属性给删除掉。

SubType.prototype.constructor = SubType;

这句是重新将构造函数属性给恢复回来,从而实现仅仅是继承了SuperType的属性方法而不改变其他属性。

《Javascript启示录》中的 8.8 用新对象替换prototype属性会删除默认构造函数属性。
可以用一个新值来替换prototype属性的默认值,然而,这么做会将删除在“预制”原型对象中找到的默认constructor属性,除非手动指定一个。


1)原型是属于一个函数对象的
2)原型是一个对象
3)以一个原型具有constructor属性,指向一个函数对象
4)在默认情况下,一个函数对象的原型的contructor属性指向这个函数对象,当然后有非默认情况的
问题中描述了默认和非默认的
默认的:

function SuperType(name){
    this.name =name;
    this.colors = ["red","blue","green"];
    this.sex = "man"
}
SuperType.prototype.sayName = function(){
    alert(this.name);
};

SuperType.prototype.constructor指向默认的SuperType函数对象;

非默认的:
上面2)有提到,prototype是指向一个对象的,那么也就意味着我可以直接赋一个对象给prototype属性

SubType.prototype = new SuperType();

就是如此-SubType通过原型链就“继承”了SuperType的prototype中定义的方法及SuperType实例方法及属性
此时的SubType.prototype.constructor就指向SuperType的实例对象的constructor,这个值就是SuperType函数

console.log(SubType.prototype.constructor===SuperType?'what\'s happen,SubType.prototype.constructor is SuperType':'SubType.prototype.constructor is not SuperType');
//输出what's happen,SubType.prototype.constructor is SuperType

如果继承代码到此为止的话,带来的一个问题就是SubType不能正确地反应其真实地constructor

var instanceSub=new SubType();
console.log(instanceSub instanceof SubType);//true
console.log(instanceSub instanceof SuperType);//true

SubType是SubType构造函数的实例,但是SubType原型的构造函数却是SuperType,这个就和原型"继承"的设计语义相违背了。

这个问题可以通过重新设置constructor来解决

SubType.prototype.constructor = SubType;

SubType原型的构造器对象指向了SubType

各归其位,各司其职

【热门文章】
【热门文章】