继承

70 阅读2分钟

JS继承的几种实现方式

设继承父类为:

   function animal(name) {
            this.name = name || 'animal';

            this.sleep = function() {
                console.log(this.name + '休息');
            }
        }
        animal.prototype.eat = function(food) {
            console.log(this.name + '在吃' + food);
        }

1.原型链继承
将父类的实例作为子类原型

        function cat() {}
        cat.prototype = new animal();
        cat.prototype.name = 'cat';

        // Test Code
        var cat = new cat();
        console.log(cat.name); //cat
        console.log(cat.eat('yu')); //cat在吃yu
        console.log(cat.sleep()); //cat在休息
        console.log(cat instanceof animal); //true 
        console.log(cat instanceof cat); //true
        
        //实例是父类实例也是子类实例
        //简单,容易实现
                

此类方法无法实现多继承,且创建子类实例时,无法向父类构造函数传参

2.构造继承
以父类构造函数增强子类实例(复制父类实例属性给子类)

    function gou(name) {
            animal.call(this);
            this.name = name || 'erha';
        }

        var gou = new gou();
        console.log(gou.name); //erha 
        console.log(gou.sleep());//erha在休息
          console.log(gou.eat('gutou')); //没用到原型继承
        console.log(gou instanceof animal); //false 
        console.log(gou instanceof gou); //true
        
        //可实现多继承
        //创建子类实例时,可向父类传参

此类方法实例为子类实例,仅能继承父类实例属性和方法,不能继承原型和方法且无法实现函数复用

3.实例继承
为父类实例添加新特性,作为子类实例返回

        function niao(name) {
            var instance = new animal();
            instance.name = name || 'wuya';
            return instance;
        }

        var niao = new niao();
        console.log(niao.name); //wuya
        console.log(niao.sleep()); //wuya在休息
        console.log(niao.eat('chong')); //wuya在吃chong
        console.log(niao instanceof animal); // true
        console.log(niao instanceof gou); // false

此类方法同样不支持多继承且实例仅为父类的实例

4.组合继承 通过调用父类构造,继承父类的属性并保留传参,通过父类实例做子类原型,实现函数复用

    function qie(name) {
            animal.call(this);
            this.name = name || 'laoda';
        }
        qie.prototype = new animal();

        qie.prototype.constructor = qie;

        // Test Code
        var qie = new qie();
        console.log(qie.name); //laoda
        console.log(qie.sleep()); //laoda在休息
        console.log(niao.eat('yu'));
        console.log(qie instanceof animal); // true
        console.log(qie instanceof Cat); // true
           

此类方法可以继承实例属性/方法,也可以继承原型属性/方法,是子类实例也是父类实例,可以传参,函数可复用

5.寄生组合继承 通过寄生方式,砍掉父类的实例属性,这样,在调用两次父类的构造的时候,就不会初始化两次实例方法/属性,避免的组合继承的缺点

        function cat(name) {
            animal.call(this);
            this.name = name || 'Tom';
        }
        (function() {
            // 创建一个没有实例方法的类
            var Super = function() {};
            Super.prototype = animal.prototype;
            //将实例作为子类的原型
            cat.prototype = new Super();
        })();

        // Test Code
        var cat = new cat();
        console.log(cat.name); //Tom
        console.log(cat.sleep()); //Tom在休息
        console.log(cat.eat('yu')); //Tom在吃yu
        console.log(cat instanceof animal); // true
        console.log(cat instanceof cat); //true

        cat.prototype.constructor = cat; // 需要修复下构造函数