js六种继承

一、什么是继承?为什么要实现继承?

子类啃老,自己想从父类获取属性和方法

二、了解一下构造函数、实例、原型对象的区别

  • 构造函数就是这样的function Fun() {} 大写的函数名,普通函数是小写
  • 实例对象就是new Fun
  • 每一个构造函数都有原型对象
    请添加图片描述instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。

三、实现继承的六种方式的优缺点

方式实现原理优点缺点
原型链继承子类原型=父类实例简单子类实例没办法给父类传值,子类共享父类实例,一改都改
构造继承父类的构造函数放到子类里子类实例可以给父类传值,子类共享父类实例,一改不全改执行两次父类函数,子类的实例无法访问父类原型上的方法
原型式继承借用原型基于已有的对象创建新对象必须有一个对象来作为另一个对象的基础,数据共享
寄生式继承Object.create()和原型式继承一样,只是封装了一下而已
寄生组合式继承解决数据共享的问题最接近ES6代码冗杂
ES6中Class类

最好的方式就是寄生组合式和ES6中的class extend

四、实现继承的六种方式

1.原型链继承(将父类的实例赋值给子类的原型)

 //定义父类
        function Parent() {
            this.name = '甜仔';
        }
        // 父类的原型添加方法
        Parent.prototype.getName = function() {
            console.log(this.name)
        }
        // 定义子类
        function Child() {

        }
        Child.prototype = new Parent(); //父类的实例等于子类的原型
        let child1 = new Child();
        console.log(child1.__proto__.name) //甜仔
        console.log(child1.name) //甜仔
        child1.getName() //甜仔

优点
1.简单易于实现,父类的实例赋值给子类的原型
缺点

  1. 子类的实例没办法给父类传值
//
        // 定义父类
        function Parent(name) {
            //属性
            this.name = name;
            // 实例方法
            this.sleep = function() {
                console.log(this.name + '正在睡美容觉')
            }
        }
        //原型方法
        Parent.prototype.eat = function(food) {
            console.log(this.name +'正在吃'+ food)
        }
        //定义子类
        function Children(name) {
           
        }
        Children.prototype = new Parent
        var wen = new  Children()
        console.log(wen.sleep()) //un正在睡美容觉
        console.log(wen.eat("火锅")) //un正在吃火锅

2.多个子类实例共享父类的属性,其中的子类实例改了属性,影响其他的子类

//
         //定义父类
        function Parent() {
            this.name = ['甜崽', '甜仔'];
        }
        // 父类的原型添加方法
        Parent.prototype.getName = function() {
            console.log(this.name)
        }
        // 定义子类
        function Child() {

        }
        Child.prototype = new Parent();
        let child1 = new Child();
        let child2 = new Child();
        child1.name.push('温小鹿');
        console.log(child1.name) //['甜崽', '甜仔', '温小鹿']
        console.log(child2.name) //['甜崽', '甜仔', '温小鹿']
        
        //其中一个子类的实例修改父类构造函数中的属性,其他的子类实例共享属性,也会访问改后的属性

2.借用构造继承(父类构造函数放到子类的构造函数中,call,apply改变指向)

 //定义父类
        function Parent() {
            this.name = ['甜崽', '甜仔'];
        }
        // 父类的原型添加方法
        Parent.prototype.getName = function() {
            console.log(this.name)
        }
        // 定义子类
        function Child(ChildName) {
            Parent.apply(this)
            this.name = ChildName
        }
        let child1 = new Child('温小鹿是他的饲养员aaa');
        console.log(child1.name) // 温小鹿是他的饲养员aaa

3.原型式继承(借用原型基于已有的对象创建新对象)

借用原型基于已有的对象创建新对象

//定义父类
        function object(o) {
            function F() {};
            F.prototype = o;
            return new F()
        }
        let test = {
            name: ['甜仔', '甜崽'],
            age: '三个月',
            getName : function() {
                return this.name + '已经' + age;
            }
        }
        let test1 = object((test)
        let test2 = object((test)
        test1.name.push('温小鹿')
        console.log(test1.name) // ['甜仔', '甜崽', '温小鹿']
        console.log(test2.name) // ['甜仔', '甜崽', '温小鹿']
        // 父类的函数内部,创建一个临时的构造函数,传入的对象作为临时构造函数的原型,返回临时的实例
        // 该继承需要有一个对象可以作为另一个对象的基础
        // 缺点,数据共享

ES5中的Object.create(新创建对象的原型对象,为新创建的对象添加指定的属性值和对应的属性描述符。)规范了原型式继承,第二个参数如果相同会覆盖

        let test = {
        name: ["甜仔", "甜崽"],
        age: "三个月",
        getName: function () {
          return this.name + "已经" + age;
        },
      };
      let test1 = Object.create(test, {
        name: {
          value: "温小鹿",
        },
        age: {
          value: 20,
        },
      });
      console.log(test1);

4.寄生式继承(封装原型式继承)

 function Parent(o) {
        var clone = Object.create(o);
        clone.getName = function () {
          console.log(this.name, "1111");
        };
        return clone;
      }
      let test = {
        name: ["甜仔", "甜崽"],
        age: "三个月",
      };
      let a = Parent(test);
      a.getName(); //['甜仔', '甜崽'] '1111'

5.寄生组合式继承

      function inheritPrototype(parent, child) {
        var clone = Object.create(parent.prototype); //创建对象
        clone.constructor = child; // 增强对象
        child.prototype = clone; // 指定对象
      }
      function Parent(name) {
        this.name = name;
      }
      Parent.prototype.getName = function () {
        console.log(this.name);
      };
      function Child(name, age) {
        Parent.call(this, name);
        this.age = age;
      }
      inheritPrototype(Parent,Child);
      var a = new Child("甜仔", 3);
      a.getName();

6. ES6中的继承

 class Parent {
        constructor(name) {
            this.name = name;
        }
        getName() {
           console.log(`我的猫叫${this.name}`)
        }
      };
      class Child extends Parent {
        constructor(name, age) {
            super(name, age);
            this.name = name;
        }
      }
      let a = new Child('甜仔', 3)
      a.getName() //我的猫叫甜仔
      console.log(a.name) //甜仔
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值