js学习中的总结——几种继承模式

        js中构造函数的几种继承模式浅析

一、原型链模式继承

    利用原型让一个引用类型继承另一个引用类型的属性和方法 。

    用的最多。

    缺点:不可传参,不可多继承。

function People(name, age) {//添加公有属性
            name = name || 'xiaolan';
            age = age || 18;
            this.name = name;
            this.age = age;
        }//创建一个名为People的类
        People.prototype.eat = function() {//添加私有属性
            console.log(this.name + '贼能吃');
        }
        function Cat(color) {//创建一个名为Cat的类
            this.color = color;
        }
        Cat.prototype = new People('小叮当', 200);//实例化一个People类,并赋值给Cat类的原型链
        var cat = new Cat('蓝白色')
        console.log(cat.name)//'小叮当'
        cat.eat();//'小叮当贼能吃'

二、混合模式继承

    用call的方法只能继承私有属性,所以再加一遍一遍原型链模式继承,原型链模式继承又把私有属性和公有属性都继承了一遍。

  function People(name, age) { //创建一个父级People类
            name = name || 'xiaolan';
            age = age || 18;
            this.name = name;
            this.age = age;
        }
        People.prototype.eat = function() {
            console.log(this.name + '贼能吃');
        }

        function Cat(color, name, age) {
            this.color = color;
            People.call(this, name, age); //通过call的形式继承
            //通过call(this),将People的指向改为Cat的实例
        }
        var cat = new Cat('蓝白色', '小叮当', 1);
        console.log(cat.name);//'小叮当'
        cat.eat();//报错,
        //继承不了公有属性,所以cat.eat()会报错;

为了继承公有属性,用原型链模式在把公有属性和方法继承过来,

 function People(name, age) { //创建一个父级People类
            name = name || 'xiaolan';
            age = age || 18;
            this.name = name;
            this.age = age;
        }
        People.prototype.eat = function() {
            console.log(this.name + '贼能吃');
        }

        function Cat(color, name, age) {
            this.color = color;
            People.call(this, name, age); //通过call的形式继承
            //通过call(this),将People的指向改为Cat的实例
        }
        Cat.prototype = new People()
        var cat = new Cat('蓝白色', '小叮当', 200)
        console.log(cat)
        console.log(cat.name); //'小叮当',在原型链继承的时候,就近原则,cat.name 先找到'小叮当',就不往下找了
        cat.eat(); //'小叮当贼能吃'

三、拷贝继承

    优点:可以多继承,可传参;

    缺点:浪费资源,不能判断父级;

        function People(name, age) { //创建一个父级People类
            name = name || 'xiaolan';
            age = age || 18;
            this.name = name;
            this.age = age;
        }
        People.prototype.eat = function() {
            console.log(this.name + '贼能吃');
        }

        function Cat(color, name, age) {
            this.color = color;
            var people = new People(name, age) //实例化一个People类
            for (let i in people) {
                this[i] = people[i]; //将people中的可枚举属性和方法遍历并附给Cat类,公有属性和私有属性都是可枚举属性;
            }
        }
        var cat = new Cat('蓝白色', '小叮当', 2);
        console.log(cat.name); //小叮当
        cat.eat(); //小叮当贼能吃

四、寄生组合方式继承

    优点:私有属性和公有属性都单独继承,可以传参;

    私有属性可以多继承,公有属性不可多继承;

        function People(name, age) {
            name = name || 'xiaolan';
            age = age || 18;
            this.name = name;
            this.age = age;
        }
        People.prototype.eat = function() {
            console.log(this.name + '贼能吃');
        }

        function Cat(color, name, age) {
            this.color = color;
            People.call(this, name, age) //用call的形式把私有属性继承过来
        }

        function Fn() {} //创建一个中间构造函数,用来接收People的公有属性,为了防止创建实例Cat实例是影响原来的people构造函数
        Fn.prototype = People.prototype;
        Cat.prototype = new Fn(); //将中间构造函数Fn继承people的公有属性传给Cat的原型链
        Cat.prototype.constructor = Cat; //由于上一步重置了Cat原型链的constructor属性,所以要重新给赋回来;
        var cat = new Cat('蓝白色', '小叮当', 3);
        console.log(cat.name); //'小叮当'
        cat.eat() //'小叮当贼能吃


注:若有不严谨与错误的地方,请多指教!


猜你喜欢

转载自blog.csdn.net/lybycm/article/details/80861384