浅谈JavaScript中继承的实现

  谈到js中的面向对象编程,都有一个共同点,选择原型属性还是构造函数,两者各有利弊,而就片面的从js的对象创建以及继承的实现两个方面来说,官方所推荐的是两个相结合,各尽其责,各取其长,在前面的例子中,我已就在JavaScript中对象创建的方法做了一些总结,下面就其继承来道说一二:

 

1:原型链继承

   每一个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象内部的指针

 

 

 

(默认的原型,所有默认类型都继承了Object,而这个继承也是用过原型链实现)
function SuperType(){
            this.property = true;
        }

        SuperType.prototype.getSuperValue = function(){
            return this.property;
        };
        function SubType(){
            this.subproperty = false;
        }

        //继承SuperType
        SubType.prototype = new SuperType();

        SubType.prototype.getSubValue = function(){
            return this.subproperty;
        };
        var instance = new SubType();
        alert(instance.property);
        
        alert(instance.getSuperValue());
        alert(instance.getSubValue());

原型继承的问题:

   1:原型属性被所有实例所共享   一个改变,其余跟着改变。
2:在创建子类型的实例时,不能向超类型的构造函数中传递参数
总结:实践中很少会单独使用原型链

(这似乎和对象创建时的问题如出一辙)

2:借用构造函数创建:
        function SuperType(){
            this.colors = ["red","blue","green"];
        }
        function SubType(){
//            继承了SubType
            SuperType.call(this);
        }
        var instance1 = new SubType();
        instance1.colors.push("black");
        alert(instance1.colors);   //["red", "blue", "green", "black"]

        var instance2 = new SubType()
        alert(instance2.colors);   //["red", "blue", "green"]没哟随某个实例
                                    //的更改而更改
//--------------------------------------------------------------------------
//        参数传递:
         function SuperType(name){
            this.name = name;
        }
        function SubType(){
//            继承了SuperType,同时还传递了参数
            SuperType.call(this , "Nicholas");
//            实例属性
            this.age = 29;
        }
        var instance = new SubType();
        alert(instance.name);  //Nicholas
        alert(instance.age);  //29

缺点:方法都在构造函数里面定义,因此函数复用就无从谈起(什么意思呢:摸索中)。

 

组合继承:

//        组合继承:
        function SuperType(name){
            this.name = name;
            this.colors = ["red","blue","green"];
        }

        SuperType.prototype.sayName = function(){
            alert(this.name);
        }

        function SubType(name , age){
            //继承属性:  调用构造函数
            SuperType.call(this , name);//第一次调用SuperType()
            this.age = age;
        }

        //继承方法:
        SubType.prototype = new SuperType(); //第二次调用SuperType()
        SubType.prototype.constructor = SubType;
        SubType.prototype.sayAge = function(){
            alert(this.age);
        };

        var instance1 = new SubType("Nicholas",29);
        instance1.colors.push("black");
        alert(instance1.colors);
        instance1.sayName();
        instance1.sayAge();


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

  自然,这种组合式创建也有其不到之处,即来两次调用了SuperType构造函数,使得实例属性colors和name的重复创建,后一次创建的自然会覆盖前面的。

 

随引出<寄生组合式继承>

上代码:

//寄生组合式继承:
        function inheritPrototype(subType , superType){
            var prototype = Object(superType.prototype);  //创建对象原型的一
//个副本
//为创建的副本添加constructor属性,使其指向自己的构造函数
            prototype.constructor = subType;//将新创建(副本)的对象赋给子类型的一个原型
            subType.prototype = prototype;
        }



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

            this.age = age;
        }
        inheritPrototype(SubType , SuperType);
        SubType.prototype.sayAge = function(){
            alert(this.age);
        };

从代码中,咋们可以看出,值调用了一次SuperType的构造函数,固然就没有什么多余的不必要的属性创建。

posted @ 2015-09-23 23:01  Lance_lou  阅读(302)  评论(0编辑  收藏  举报