美文网首页
对象的继承

对象的继承

作者: Sanyekui | 来源:发表于2019-11-04 17:42 被阅读0次

    JS 作为面向对象的弱类型的语言,继承是它非常强大的特征之一

    JS继承实现的方式:

    1.原型链继承
    2.构造函数继承
    3.实例继承
    4.拷贝继承
    5.组合继承和寄生继承

    原型链继承:

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

    function Animal(name){//创建一个父类 Animals
        this.name = name;//属性
        this.sleep = function(){//方法
            return this.name+"在睡觉";
        }
    }
    
    //给父类 Animal 加一个原型方法:
    Animal.prototype.eat = function(food){
        return this.name + "正在吃" + food;
    }
    
    //原型链继承核心: 将父类的实例作为子类的原型
    function Cat(age){
        this.age = 12;
    }//创建一个子类
    
    Cat.prototype = new Animal();//把Animal父类的实例赋给子类的原型
    //若子类需要新增属性和方法必须放在它的后边
    Cat.prototype.name = "cat";
    //给子类新增一个原型属性name 相当于是 Animal父类的 this.name = "cat"; 但不会影响父类
                            
    Cat.prototype.run = function(){
        return this.name + this.age + this.sleep();
    }               
    var cat = new Cat();
    console.log(cat.name);//cat 
    console.log(cat.eat("fish"));//cat正在吃fish
    console.log(cat.sleep());//cat在睡觉
    console.log(cat instanceof Cat);//turn
    console.log(cat instanceof Animal);//turn
    console.log(cat.run());//cat12cat在睡觉
    
    
    原型链继承的特点和缺点:
    特点:

    1.非常纯粹的继承关系,它实例既是子类的实例,也是父类的实例
    2.父类新增的原型方法和属性,子类都是可以访问的到的
    3.简单,方便

    缺点:

    1.如果子类要新增属性和方法,必须要放在new 父类()这2.样的语句之后执行
    3.无法实现多继承的
    4.来自原型的所有属性被所有实例所共享
    5.创建子类实例时,无法向父类构造函数传参


    构造函数的继承:

    使用父类的构造函数来增强子类的实例,其实就是复制父类的实例属性给子类,不用到原型链

    function Animal(name){//创建一个父类 Animals
        this.name = name;//属性
        this.sleep = function(){//方法
            return this.name+"在睡觉";
        }
    }
    function Dog(name){
        Animal.call(this);
    //属性使用对象冒充,其实就是改变this指向,继承父类
    //this 相当于 new Animal
        this.name = name;
        Cat.call(this);//可以实现多个父类继承
    }
    var dog = new Dog("dog");
    console.log(dog.name);//dog
    console.log(dog.sleep())//dog在睡觉
    console.log(dog.name);//dog
    console.log(dog.age);//12
                
    //console.log(dog.eat("狗粮"));//无法访问父类原型对象上的方法
    console.log(dog instanceof Dog);//ture
    console.log(dog instanceof Animal);//false,不能继承父类的原型对象
    
    
    构造函数继承的特点和缺点:
    特点:

    1.创建子类实例的时候,可以向父类传递参数
    2.可以实现多个继承(call多个父类对象)

    缺点:

    1.实例是子类的实例,不是父类的实例
    2.只能继承父类实例的属性和方法,不能继承父类的原型属性和方法
    3.无法实现函数复用,每个子类都有父类实例函数的副本,影响性能


    实例继承:

    为父类的实例添加新的属性,作为子类实例的返回值

    function Animal(name){//创建一个父类 Animals
        this.name = name;//属性
        this.sleep = function(){//方法
            return this.name+"在睡觉";
        }
    }
    //给父类 Animal 加一个原型方法:
    Animal.prototype.eat = function(food){
        return this.name + "正在吃" + food;
    }
    
    function Sheep(name){
        var animal = new Animal();//把父类的实例赋给animal
        animal.name = name;//给实例添加属性 
        return animal;//返回属性值 作为子类的实例返回,但还是属于父类的实例
    }
                
    var sheep = new Sheep("Xiaoen");
    //var sheep = Sheep("Xiaoen");
    console.log(sheep.name);//Xiaoen
    console.log(sheep.sleep());//Xiaoen在睡觉
    console.log(sheep.eat("草"));//Xiaoen在吃草
    console.log(sheep instanceof Sheep);//false
    console.log(sheep instanceof Animal);//ture
    
    
    实例继承的特点和缺点:

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

    缺点:
    实例是父类的实例,不是子类的实例
    不支持多继承,因为函数的返回值只有一个


    拷贝继承:(少用)

    支持多继承,效率低,内存占用高(因为要拷贝父类的属性和方法)
    没有办法获取父类不可枚举的方法(不可枚举的方法不能使用for in 遍历)


    寄生组合继承:

    核心:通过寄生方式,砍掉父类的实例属性,这样,在调用两次父类的构造函数时,
    就不会初始化两次实例的方法和属性,避免了组合继承的缺点
    核心:通过调用父类构造,继承父类的属性并且保留传参的优点,
    然后通过将父类实例作为子类原型,实现函数复用

    function Animal(name){//创建一个父类 Animals
        this.name = name;//属性
        this.sleep = function(){//方法
            return this.name+"在睡觉";
        }
    }
    function Rubbit(name){
        Animal.call(this);
        this.name = name;
    }
    Rubbit.prototype = new Animal();
    Rubbit.prototype.constructor = Rubbit;//组合继承需要修复构造函数的指向
                
    var rubbit = new Rubbit("小白兔");
    console.log(rubbit.name);//小白兔
    console.log(rubbit.sleep());//小白兔在睡觉
    console.log(rubbit instanceof Rubbit);//true
    console.log(rubbit instanceof Animal);//true
    
    

    组合继承的特点和缺点:

    特点:
    实例既是父类的实例,也是子类的实例
    可以继承实例的方法和属性,也可以继承原型的方法和属性
    可以传参
    函数可以重复使用

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


    寄生组合继承:

    核心:通过寄生方式,砍掉父类的实例属性,这样,在调用两次父类的构造函数时,
    就不会初始化两次实例的方法和属性,避免了组合继承的缺点

    function Animal(name){//创建一个父类 Animals
        this.name = name;//属性
        this.sleep = function(){//方法
            return this.name+"在睡觉";
        }
    }
    //给父类 Animal 加一个原型方法:
    Animal.prototype.eat = function(food){
        return this.name + "正在吃" + food;
    }
    
    function Pig(name){
        Animal.call(this);
        this.name = name;
    }
    (function(){
        var obj = function(){}//创建一个没有实例方法的类
        obj.prototype = Animal.prototype;
        //将父类的原型传给这个没有实例方法的类的原型
        Pig.prototype = new obj();//将实例作为子类的原型
    })();
    
    Pig.prototype.constructor = Pig;//修复构造函数指向
                
    var pig = new Pig('佩奇');
    console.log(pig.name);//佩奇
    console.log(pig.sleep());//佩奇在睡觉
    console.log(pig.eat("垃圾"));//佩奇在吃垃圾
    console.log(pig instanceof Pig);//true
    console.log(pig instanceof Animal);//true
    
    

    特点:完美

    缺点:实现起来比较复杂

    相关文章

      网友评论

          本文标题:对象的继承

          本文链接:https://www.haomeiwen.com/subject/vjedbctx.html