js继承-构造函数继承

源自:https://www.bilibili.com/video/BV1J54y1y7u9/spm_id_from=333.999.0.0&vd_source=e3be50d480f221289d42a33a50f4ec8a

1、构造函数继承

    <script>
      //1、 创建父类构造函数Parent
      function Parent(name) {
        this.name = name; // 实例基本属性 (该属性,强调私有,不共享)
        this.arr = [1]; // (该属性,强调私有)
        this.say = function () {
          // 实例引⽤属性 (该属性,强调复⽤,需要共享)
          console.log("hello");
        };
      }
      //2、 创建父类构造函数Child
      function Child(name, like) {
        Parent.call(this, name); // 核⼼ 拷⻉了⽗类的实例属性和⽅法
        this.like = like;
      }
      //3、子类实例
      let boy1 = new Child("⼩红", "apple");
      let boy2 = new Child("⼩明", "orange ");
      // 优点1:可向⽗类构造函数传参
      console.log(boy1.name, boy2.name); // ⼩红, ⼩明
      // 优点2:不共享⽗类构造函数的引⽤属性
      boy1.arr.push(2);
      console.log(boy1.arr, boy2.arr); // [1,2] [1]
      // 缺点1:⽅法不能复⽤
      console.log(boy1.say === boy2.say); // false (说明,boy1和boy2的say⽅法是独⽴,不是共享的)
      // 缺点2:不能继承⽗类原型上的⽅法
      Parent.prototype.walk = function () {
        // 在⽗类的原型对象上定义⼀个walk⽅法。
        console.log("我会⾛路");
      };
      boy1.walk; // undefined (说明实例,不能获得⽗类原型上的⽅法)
    </script>

2、原型链继承

<script>
      // 1、创建父类构造函数Parent
      function Parent(name) {
        this.name = name || "⽗亲"; // 实例基本属性 (该属性,强调私有,不共享)
        this.arr = [1]; // (该属性,强调私有)
      }
      //2、将需要复⽤、共享的⽅法定义在⽗类Parent原型上
      Parent.prototype.say = function () {
        console.log("hello");
      };
      // 3、创建子类构造函数Child
      function Child(like) {
        this.like = like;
      }

      //4、将Parent的实例赋值给Child的原型对象,Child实例化的对象就可以继承到Parent的属性和方法
      Child.prototype = new Parent(); // 核⼼,此时Child.prototype.constructor==Parent
      Child.prototype.constructor = Child; // 修正constructor指向
      let boy1 = new Child();
      let boy2 = new Child();
      // 优点:共享了⽗类构造函数的say⽅法
	  console.log(boy1.say(), boy2.say(), boy1.say === boy2.say); // hello , hello , true
	  // 缺点1:不能向⽗类构造函数传参
	  console.log(boy1.name, boy2.name, boy1.name===boy2.name); // ⽗亲,⽗亲,true
	 // 缺点2: ⼦类实例共享了⽗类构造函数的引⽤属性,⽐如arr属性
	  boy1.arr.push(2);
	  // 修改了boy1的arr属性,boy2的arr属性,也会变化,因为两个实例的原型上(Child.prototype)有了⽗类构造函数的实例属性arr;
	  所以只要修改了boy1.arr,boy2.arr的属性也会变化。
	  console.log(boy2.arr); // [1,2]
	  注意1:修改boy1的name属性,是不会影响到boy2.name。因为设置boy1.name相当于在⼦类实例新增了name属性。
	  注意2:
	  console.log(boy1.constructor); // Parent 你会发现实例的构造函数居然是Parent。
	  ⽽实际上,我们希望⼦类实例的构造函数是Child,所以要记得修复构造函数指向。
	  修复如下:Child.prototype.constructor = Child;
</script>

3、组合继承(构造函数+原型链)

<script>
      //1、 创建父类构造函数Parent
      function Parent(name) {
        this.name = name; // 实例基本属性 (该属性,强调私有,不共享)
        this.arr = [1]; // (该属性,强调私有)
      }
      // 2、将需要复⽤、共享的⽅法定义在⽗类原型上
      Parent.prototype.say = function () {
        console.log("hello");
      };
      // 3、创建子类构造函数Child
      function Child(name, like) {
        //通过call方法将子类构造函数的this对象指向父类
        Parent.call(this, name, like); // 核⼼ 第⼆次
        this.like = like;
      }
      //4、Parent的实例对象赋值给Child的prototype
      Child.prototype = new Parent(); // 核⼼ 第⼀次
      Child.prototype.constructor = Child; // 修正constructor指向
      let boy1 = new Child("⼩红", "apple");
      let boy2 = new Child("⼩明", "orange");
      // 优点1:可以向⽗类构造函数传参数
      console.log(boy1.name, boy1.like); // ⼩红,apple
      // 优点2:可复⽤⽗类原型上的⽅法
      console.log(boy1.say === boy2.say); // true
      // 优点3:不共享⽗类的引⽤属性,如arr属性
      boy1.arr.push(2);
      console.log(boy1.arr, boy2.arr); // [1,2] [1] 可以看出没有共享arr属性。
      // 缺点1:由于调⽤了2次⽗类的构造⽅法,会存在⼀份多余的⽗类实例属性
    </script>
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值