js继承的四种实现方式

一、原型链继承

核心:将父类的实例作为子类的原型。

        //声明一个动物的类
        function Animal(name){
            this.name=name;
            this.eat=function(){
                return this.name+"正在吃"
            }
        }
        Animal.prototype.sex="公"; //父类新增原型方法/原型属性,子类都能访问到
        Animal.prototype.age="3";
        Animal.prototype.sleep=function(){
            return this.name+"正在睡觉"
        }
        Animal.prototype.weight="20kg";
        //声明一个子类
        function dog(){

        }
        /* 原型链继承   直接原型一个父类*/
        dog.prototype=new Animal();  //要想为子类新增属性和方法,必须要在new Animal()这样的语句之后执行,不能放到构造器中无法实现多继承
        dog.prototype.name="哈士奇";
        dog.prototype.weight="50kg";
        var Dog=new dog();//创建子类实例时,无法向父类构造函数传参
        console.log(Dog.name);//哈士奇
        console.log(Dog.eat());//哈士奇正在吃
        console.log(Dog.sleep());//哈士奇正在睡觉
        console.log(Dog.weight);//50kg
        console.log(Dog instanceof dog);   //true          //实例是子类的实例,也是父类的实例
        console.log(Dog instanceof Animal);//true

        //动物类实例化为对象
        var animal=new Animal("猫");
        console.log(animal.name);
        console.log(animal.eat());
        console.log(animal.sex);
        console.log(animal.sleep());

特点:非常纯粹的继承关系,实例是子类的实例,也是父类的实例。

          父类新增原型方法/原型属性,子类都能访问到。

          简单,易于实现。

缺点:要想为子类新增属性和方法,必须要在new Animal()这样的语句之后执行,不能放到构造器中,无法实现多继承。

二、构造继承

核心:使用父类的构造函数来增强子类实例,等于是复制父类的实例属性给子类(没用到原型)

        function Animal(name,sex,age){
            this.name=name;
            this.sex=sex;
            this.age=age;
            this.eat=function(){
                return this.name+"正在吃饭";
            }
        }
        Animal.prototype.color=function(){
            return "白色"
        }
        function Type(type){
            this.type=type;
        }
        Type.prototype.weight=function(){
            return "20kg"
        }
        function dog(name2,sex2,age2,type2){
            Animal.apply(this);
            Type.apply(this,arguments);//可以实现多继承(call多个父类对象)
            this.name=name2;
            this.sex=sex2;
            this.age=age2;
            this.type=type2;
        }
        var Dog=new dog("萨摩","公","3岁","犬类");//创建子类实例时,可以向父类传递参数 实例并不是父类的实例,只是子类的实例
        console.log(Dog.name);//萨摩
        console.log(Dog.sex);//公
        console.log(Dog.age);//3岁
        console.log(Dog.eat());//萨摩正在吃饭
        console.log(Dog.type);//犬类
        /*只能继承父类的实例属性和方法,不能继承原型属性/方法*/
        /*console.log(Dog.weight());
        console.log(Dog.color())*///会报错

特点:

        创建子类实例时,可以向父类传递参数

        可以实现多继承(call多个父类对象)

缺点:

        实例并不是父类的实例,只是子类的实例

        只能继承父类的实例属性和方法,不能继承原型属性/方法

        无法实现函数复用,每个子类都有父类实例函数的副本,影响性能

三、组合继承

        function Animal(name){
            this.name=name;
            this.eat=function (){
                return this.name+"正在吃饭";
            }
        }
        Animal.prototype.sleep=function (){
            return this.name+"正在睡觉";
        }
        function Cat(name){
            Animal.call(this,name);  //构造继承
        }
        //原型链继承
        Cat.prototype=new Animal();
        var cat=new Cat("mao");
        console.log(cat.name);//mao
        console.log(cat.eat());//mao正在吃饭
        console.log(cat.sleep());//mao正在睡觉

特点:

        弥补了方式二的缺陷,可以继承实例属性/方法,也可以继承原型属性/方法

        既是子类的实例,也是父类的实例

        不存在引用属性共享问题   可传参   函数可复用

缺点:调用了两次父类构造函数,生成了两份实例(子类实例将子类原型上的那份屏蔽了)

四、实例继承

        function Animal(name){
           this.name=name;
            this.eat=function (){
                return this.name+"正在吃饭!";
            }
        }
        Animal.prototype.sleep=function (){
            return this.name+"正在睡觉";
        }
        function Cat(){
            var instances=new Animal();
            instances.name="mao";
            return instances;
        }
        var cat=new Cat();
        console.log(cat.name);//mao
        console.log(cat.eat());//mao正在吃饭
        console.log(cat.sleep());//mao正在睡觉

特点:

        不限制调用方式,不管是new 子类()还是子类(),返回的对象具有相同的效果

缺点:

        实例是父类的实例,不是子类的实例

        不支持多继承


猜你喜欢

转载自blog.csdn.net/qq_41985171/article/details/80521723