JavaScript继承的多种方式及优缺点

1.原型链继承

1.1 实现方式

function Person(sing) {
  this.sing = sing;
  this.jump = function () {
    console.log("jump");
  };
}
Person.prototype.rap = function () {
  console.log("rap");
};

function Children() {}

// 将 Person 构造函数的实例对象赋值给 Children 构造函数的原型,Children 就能拿到 Person 中所有的属性及方法
Children.prototype = new Person("sing");

const c1 = new Children();
const c2 = new Children();
console.log(c1.sing);
c1.jump();
c1.rap();

输出结果:

在这里插入图片描述

1.2 优缺点

  • 优点:实现简单,一行代码
  • 缺点:数据共享了,c1和c2共享了同一个原型对象

2.借用构造函数继承

1.实现方式

function Person(sing) {
  this.sing = sing;
  this.jump = function () {
    console.log("jump");
  };
}
function Children(sing) {
  // this -> Children 的实例对象
  Person.call(this, sing);
}
const c1 = new Children("sing1");
const c2 = new Children("sing2");
console.log(c1.sing);
console.log(c2.sing);
c1.jump();

输出结果:

在这里插入图片描述

2.2 优缺点

  • 优点:
    • 避免了引用类型的属性被所有的实例共享;
    • 可以在 Children 中向 Person 传参
  • 缺点:
    • 方法都在构造函数中定义,每次创建实例都会创建一遍方法;
    • 不能继承 Person 原型上的方法/属性
    Person.prototype.rap = function () {
      console.log("rap");
    };
    c1.rap(); // 这样去使用的话会报错 rap 未定义
    

3.组合继承

3.1.实现方式

  • Person.call(this, sing); // 借用构造器
  • Children.prototype = new Person(); // 原型链继承,能继承原型上的方法
  • Children.prototype.constructor = Children; // 将构造函数引用指向 Children
function Person(sing) {
  this.sing = sing;
  this.jump = function () {
    console.log("jump");
  };
}
Person.prototype.rap = function () {
  console.log("rap");
};
function Children(sing, ball) {
  // this -> Children 的实例对象
  Person.call(this, sing); // 借用构造器
  this.ball = ball;
}

Children.prototype = new Person(); // 原型链继承,能继承原型上的方法

/**
 * 如果不显式地将 Children.prototype.constructor 设置为 Children,
 * 那么 Children.prototype.constructor 将会指向 Parent,
 * 因为 Children.prototype 是基于 Parent.prototype 创建的。
 * 这显然是不正确的,因为 Children.prototype 应该与 Children 构造函数相关联。
 */
Children.prototype.constructor = Children; // 将构造函数引用指向 Children
const c1 = new Children("sing1");
const c2 = new Children("sing2");
console.log(c1.sing);
console.log(c2.sing);
c1.jump();
c1.rap();

3.2 优缺点

  • 融合原型链继承和构造函数的优点,是 JavaScript 中最常用的继承模式

4.寄生式继承

4.1.实现方式

function createObj(o) {
  var clone = Object.create(o);
  clone.sayName = function () {
    console.log("hi");
  };
  return clone;
}
let c = createObj({
  hello: "world",
});
console.log(c.hello); // world
c.sayName(); // hi

输出结果:
在这里插入图片描述

5. ES6中的 class 继承

5.1 基本实现

  • 通过 class 关键字声明类
  • 子类通过 extends 关键字继承父类
class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
  say() {
    console.log("say");
  }
}

class Children extends Person {}

let c1 = new Children("嘎子", 18);
let c2 = new Children("英子", 22);
console.log(c1.name);
console.log(c1.age);
console.log(c1.say);
console.log(c2.name);
console.log(c2.say);
  • 输出结果
    在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

剑九_六千里

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值