JavaScript继承

原型链继承

function SuperType() {
           this.property = true;
       }
        //  在原型链上定义方法。
       SuperType.prototype.getSuperValue = function (){
           return this.property;
       }

       function SubType() {
           this.subproperty = false;
       }

        //  替换SubType原型,达到继承效果。
       SubType.prototype = new SuperType();

        //  开始写SubType的方法,注:SubType的方法必须写在替换SubType原型语句后
       SubType.prototype.getSubValue = function (){
           return this.subproperty;
       }

       var instance = new SubType();
       alert(instance.getSuperValue());

原型链继承的原理如期名,是利用建立父类(SuperType)的实例,并将该实例赋值给子类(SubType).prototype实现的,实质是重写子类的原型对象。app

原型链继承特色:函数

  • 引用类型值的原型属性会被全部实例共享。
  • 在建立子类型的实例时,没办法再不影响全部对象实例的状况下向超类传递参数。
  • 即实现全部属性方法共享,但没法作到属性、方法独享

借用构造函数继承

function SuperType() {
            this.colors = ['red','blue','green'];
        }

        function 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

借用构造函数继承(constructor stealing),该继承思想很简单,即在子类型构造函数的内部调用超类型构造函数便可。经过call()方法(或apply()方法也能够),实质上是在(将来将要)新建立的SubType实例的环境下调用SuperType构造函数。工具

借用构造函数继承特色:this

  • 能够在子类型构造函数中向超类型构造函数传递参数。
  • 方法都在构造函数中定义,没法实现函数复用。
  • 超类型的原型中定义的方法对子类不可见。
  • 即实现全部属性独享,但没法作到方法继承

组合继承

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('Y',21);
        instance1.colors.push('black');
        alert(instance1.colors);  //red,blue,green,black
        instance1.sayName();  //Y
        instance1.sayAge();  //21

        var instance2 = new SubType('Z',22);
        alert(instance2.colors);  //red,blue,green
        instance2.sayName();  //Z
        instance2.sayAge();  //22

组合继承(combination inheritance)又叫伪经典继承,是JavaScript中最经常使用的继承模式。组合继承指的是将原型链继承和借用构造函数继承的技术组合到一块,从而发挥两者之长的一种继承模式。该模式经过借用构造函数继承属性,经过从新子类型prototype继承方法。spa

组合继承特色:prototype

  • 实现了全部方法共享,属性独享
  • instanceof()和isprototypeOf()可以识别基于组合继承建立的对象。
  • 实现的时候调用了两次超类(父类),产生多余属性。

原型式继承

//  工具函数,实质是对传入的对象执行一次浅拷贝。
        function object(o) {
            function F() {}
            F.prototype = o;
            return new F();
        }

        var person = {
            name:'Y',
            friends:['S','C','V'],
            say:function () {
                alert(this.friends);
            }
        };

        var anotherPerson = object(person);
        anotherPerson.name = 'G';
        anotherPerson.friends.push('R');

        var yetAnotherPerson = object(person);
        yetAnotherPerson.name = 'L';
        yetAnotherPerson.friends.push('B');

        person.friends.push('my');

        anotherPerson.say();  //S,C,V,R,B,my
        alert(person.friends);  //S,C,V,R,B,my

原型式继承是由道格拉斯·克罗克福德提出的,该模式要求你必须有一个对象能够做为另一个对象的基础。该模式将一个对象传递给object()函数,而后再根据具体需求对获得的对象加以修改便可。设计

原型式继承特色:code

  • 以传入object的对象为原型,拷贝一个副本并反回。
  • 作不到函数复用,致使效率低。
  • 对象的引用类型全部实例共享(person的引用类型friends不只属于person全部,并且也会被antherPerson和yetAnotherPerson共享)。

寄生式继承

function object(o) {
            function F() {}
            F.prototype = o;
            return new F();
        }

        function createAnother(original) {
            var clone = object(original);
            clone.sayHi = function (){
                alert(this.friends);
            };
            return clone;
        }
        var person = {
            name:'Y',
            friends:['S','C','V']
        };

        var anotherPerson = createAnother(person);
        anotherPerson.friends.push('test');
        anotherPerson.sayHi();

        var anotherPerson2 = createAnother(person);
        anotherPerson2.sayHi();

寄生式继承(parasitic)一样是由克罗克福德提出并推广而之的。该模式建立一个仅用于封装继承过程的函数,该函数的内部以某种方式加强对象,最后再像真地式它作了全部工做同样返回对象。对象

寄生式继承特色:继承

  • 作不到函数复用,致使效率低。
  • 对象的引用类型全部实例共享

寄生组合式继承

function object(o) {
            function F() {}
            F.prototype = o;
            return new F();
        }
        
        //  将超类型的prototype浅拷贝一遍并赋值给子类型的prototype
        //  (至关于利用超类型prototype重写子类型prototype以达到继承效果)
        function inheritPrototype(subType,superType) {
            var prototype = object(superType.prototype);
            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);
        }

        var instance1 = new SubType('Y',21);
        instance1.colors.push('black');
        alert(instance1.colors);  //red,blue,green,black
        instance1.sayName();  //Y
        instance1.sayAge();  //21

        var instance2 = new SubType('Z',22);
        alert(instance2.colors);  //red,blue,green
        instance2.sayName();  //Z
        instance2.sayAge();  //22

原理如图:
图片描述

寄生组合式继承解决了组合继承最大的问题——不管什么状况下,都会调用两次超类型构造函数。该模式思路是:没必要为了指定子类型的原型而调用超类型的构造函数,咱们所需的无非就是超类型原型的副本而已。本质上,就是使用寄生式继承来继承超类型的原型,而后再将结果指定给子类型的原型。

寄生组合式继承特色:

  • 实现了全部方法共享,属性独享
  • instanceof()和isprototypeOf()可以识别基于组合继承建立的对象。

参考自《JavaScript高级程序设计》

相关文章
相关标签/搜索