1. 程式人生 > 其它 >js7種繼承方式

js7種繼承方式

1.原型鏈繼承

     // 核心:將父類的例項作為子類的原型
        // 核心程式碼
        // SubType.prototype = new SuperType() 
        // // 所有涉及到原型鏈繼承的繼承方式都要修改子類建構函式的指向,否則子類例項的建構函式會指向SuperType。
        // SubType.prototype.constructor = SubType;
        function Father(){
            this.a = 100
        }

        Father.prototype.fn = function
(){ console.log(123); } function Son(){ this.b = 200 } Son.prototype = new Father() Son.prototype.fn1 = function(){ console.log(222); } // 所有涉及到原型鏈繼承的繼承方式都要修改子類建構函式的指向,否則子類例項的建構函式會指向SuperType。 Son.prototype.constructor = Son
var obj = new Son() console.log(obj); // 缺點: // 1. 子型別在例項化時不能給父型別的建構函式傳參

2.借用建構函式繼承

     // 核心:將父類建構函式的內容複製給了子類的建構函式。這是所有繼承中唯一一個不涉及到prototype的繼承。
        // SuperType.call(SubType);


        // 把Father當成是普通函式來使用
        function Father(a){
            this.a = a;
            //方法不能複用
this.fn = function(){ console.log(123); } } // Father.prototype.fn = function(){ // console.log(123); // } function Son(a){ Father.call(this,a)// this是obj例項 } var obj = new Son(100) console.log(obj); // 優點 借用建構函式的一個優點就是可以在子類建構函式中向父類建構函式傳參 // 缺點:父類的方法不能複用,子類例項的方法每次都是單獨建立的。

3.組合繼承

      // 組合繼承 = 原型鏈繼承 + 借用建構函式繼承
        // 原型鏈繼承:例項的引用型別共享
        // 借用建構函式繼承:例項的引用型別不共享
        function Father(a){
            this.a = a
        }

        Father.prototype.fn = function(){
            console.log(123);
        }

        function Son(a){
            Father.call(this,a)//第二次呼叫Father
            this.b = 200
        }

        Son.prototype = new Father()//第一次呼叫Father
        Son.prototype.fn1 = function(){
            console.log(222);
        }
        Son.prototype.constructor = Son 
        var obj = new Son(100)
        console.log(obj);

        // 基本的思路是使用原型鏈繼承原型上的屬性和方法,而通過借用建構函式繼承例項屬性
        // 組合繼承彌補了原型鏈和借用建構函式的不足,是 JavaScript 中使用最多的繼承模式
        
        // 優點:
        // 1. 父類的方法可以被複用
        // 2. 子類構建例項時可以向父類傳遞引數
        // 問題:父建構函式使用了兩次
        // 屬性可能就有二個,一個是例項的,一個是原型上的

4.原型式繼承

        // 優點:父類方法可以複用
        var father = {
            a:1,
            b:2,
            fn(){
                console.log(111);
            }
        }

        var son1 = Object.create(father)
        console.log(son1);
        son1.fn()

        // 缺點:
        // 1. 子類構建例項時不能向父類傳遞引數

5.寄生式繼承

     // 使用原型式繼承獲得一個目標物件的淺複製,然後增強這個淺複製的能力。
        // 寄生式繼承就是把原型式繼承再次封裝,然後在物件上擴充套件新的方法,再把新物件返回
        // 沒什麼用

        // 增強版原型式繼承

        var father = {
            a:1,
            b:2,
            fn(){
                console.log(111);
            }
        }

        function factory(o,num){
            var obj = Object.create(o)
            obj.a = num 
            obj.fn1 = function(){
                console.log(123);
            }
            return obj 
        }

        var son1 = factory(father,100)
        console.log(son1);
        son1.fn()

6.寄生式組合繼承

     // 組合繼承其實也存在效率問題。最主要的效率問題就是父類建構函式始終會被呼叫兩次:一次在是
        // 建立子類原型時呼叫,另一次是在子類建構函式中呼叫。本質上,子類原型最終是要包含超類物件的所
        // 有例項屬性,子類建構函式只要在執行時重寫自己的原型就行了

        function fn(Son,Father){
            var subProto = Object.create(Father.prototype)// 建立了父類原型的淺複製
            subProto.constructor = Sub // 修正原型的建構函式
            Sub.prototype = subProto// 將子類的原型替換為這個原型
        }

        function Super(name){
            this.name = name 
        }

        Super.prototype.sayHi = function(){
            console.log(this.name);
        }

        function Sub(name){
            Super.call(this,name)//屬性可以傳參 借用建構函式的方式
        }

        // 核心:因為是對父類原型的複製,所以不包含父類的建構函式,也就不會呼叫兩次父類的建構函式造成浪費
        fn(Sub,Super)

        Sub.prototype.sayHello = function(){
            console.log('sayHello');
        }

        var o = new Sub('zs')
        console.log(o);

7.class類式繼承

  class Son extends Father{

        }