阅读 38

【3】JS 继承机制之六种继承方式(二)

了解了上面的基础概念,就要将学到的用在实际当中,到底要怎么实现继承呢?实现的方式有哪些?下面主要说明实现继承最常用的三用方式,可以满足基本的开发需求,想要更深入的了解,可以参考阮一峰老师的网络博客
想要实现继承,先提供一个父类,并给构造函数添加参数,以及原型属性。
function Person(name){
    this.name =  name;
    this.type =  'father';
    this.sum = function(){
        console.log("father'name",this.name);
    }
}
Person.prototype.age = 10;
Person.prototype.sayName = function(){
    console.log('superType');
}复制代码

一、原型链继承

<!-- 原型链继承 --> 
    function Per_1(){
        this.name = 'per_1_name';
    }
    Per_1.prototype = new Person();
    var per1 = new Per_1();
    console.log(per1.age);  //10
    console.log(per1 instanceof Person);
    console.log(per1.sum()) //能够输出,但是报undefined复制代码

重点:让新实例的原型等于父类的实例。

特点:1、实例可继承的属性有:实例的构造函数的属性,父类构造函数属性,父类原型                    的属性。(新实例不会继承父类实例的属性!)

缺点:1、新实例无法向父类构造函数传参。

   2、继承单一。

     3、所有新实例都会共享父类实例的属性。(原型上的属性是共享的,一个实例修                   改了原型属性,另一个实例的原型属性也会被修改!)

二、借用构造函数继承

<!-- 借用构造函数继承 -->
    function Per_2(){
        Person.call(this,'jarmer');
        this.age = 12;
    }
    var per2 = new Per_2();
    console.log(per2.name); //jarmer
    console.log(per2.age);  //12复制代码

重点:用.call()和.apply()将父类构造函数引入子类函数(在子类函数中做了父类函数的自            执行(复制))

特点:1、只继承了父类构造函数的属性,没有继承父类原型的属性。

   2、解决了原型链继承缺点1、2、3。

   3、可以继承多个构造函数属性(call多个)。

   4、在子实例中可向父实例传参。

缺点:1、只能继承父类构造函数的属性。

   2、无法实现构造函数的复用。(每次用每次都要重新调用)

   3、每个新实例都有父类构造函数的副本,臃肿。

三、组合继承

<!-- 组合继承 -->
    function Per_3(name){
        Person.call(this,name);
    }
    Per_3.prototype = new Person();
    var per3 = new Per_3('jane');
    console.log(per3.name);
    console.log(per3.age);复制代码

特点:1、可以继承父类原型上的属性,可以传参,可复用。

   2、每个新实例引入的构造函数属性是私有的。

缺点:调用了两次父类构造函数(耗内存),子类的构造函数会代替原型上的那个父类构            造函数。

四、原型式继承

<!-- 原型式继承 -->
    function Content(obj){
        function F(){}
        F.prototype = obj;
        return new F();
    }
    var per4 = new Person();
    var per4_2 = Content(per4);
    console.log(per4_2.age);
    console.log(per4_2.name);复制代码

重点:用一个函数包装一个对象,然后返回这个函数的调用,这个函数就变成了个可以随            意增添属性的实例或对象。object.create()就是这个原理。

特点:类似于复制一个对象,用函数来包装。

缺点:1、所有实例都会继承原型上的属性。

   2、无法实现复用。(新实例属性都是后面添加的)

五、寄生式继承

<!-- 寄生式继承 -->
    function Per_5(obj){
        var per5 = Content(obj);
        per5.age = 20;
        per5.name = 'tom';
        return per5;
    }
    var per6 = new Person();
    var per7 = Per_5(per6);
    console.log(typeof Per_5);  //function
    console.log(typeof per7);   //object
    console.log(per7.name); //tom复制代码

重点:就是给原型式继承外面套了个壳子。

优点:没有创建自定义类型,因为只是套了个壳子返回对象(这个),这个函数顺理成章            就成了创建的新对象。

缺点:没用到原型,无法复用。

六、寄生组合式继承 (常用)

<!-- 寄生组合式继承 (常用) -->
    function inheritPrototype(subType,superType){
        var prototype = superType.prototype;
        prototype.constructor = subType;
        subType.prototype = prototype;
    }
    function subType(name){
        Person.call(this,name);
    }
    inheritPrototype(subType,Person);
    var per8 = new subType('inheritPrototype');
    console.log(per8.age);  //10
    console.log(per8.name);  //inheritPrototype复制代码

重点:就是给原型式继承外面套了个壳子。

优点:没有创建自定义类型,因为只是套了个壳子返回对象(这个),这个函数顺理成章 就成了创建的新对象。

缺点:没用到原型,无法复用。



关注下面的标签,发现更多相似文章
评论