JavaScript 继承详解

一、原型链继承

原型链继承是 JavaScript 中最基本的继承方式。在原型链继承中,子类对象的原型指向其父类对象,通过这样的方式实现了继承。

代码示例:

function Parent() {
  this.name = "parent";
}

Parent.prototype.getName = function () {
  console.log(this.name);
}

function Child() {}
Child.prototype = new Parent();

var child = new Child();
child.getName(); // "parent"

实现原理:当访问 child.getName() 时,JavaScript 引擎会先查找 child 对象身上是否有此方法,没有则去原型链中的 Parent.prototype 上查找,找到了则执行,否则继续向上查找,直到找到 Object.prototype。

优点:代码简单易懂,易于实现。

缺点:原型链继承会将父类的引用类型属性共享给所有子类实例,容易造成意外修改,同时无法向父类构造函数传递参数。

二、借用构造函数继承(经典继承)

借用构造函数继承是在子类构造函数内部调用父类构造函数,并通过 call 或 apply 方法将父类实例绑定到子类实例上,从而实现继承。

代码示例:

function Parent(name) {
  this.name = name;
}

function Child(name) {
  Parent.call(this, name);
}

var child = new Child("child");
console.log(child.name); // "child"

实现原理:通过在子类构造函数内部调用父类构造函数,并绑定 this,从而实现了继承。借用构造函数继承避免了父类引用类型属性被共享的问题。

优点:避免了引用类型属性被共享的问题,同时可以向父类构造函数传递参数。

缺点:每次都需要调用父类构造函数,无法复用父类原型对象上的方法,导致内存浪费,并且子类实例无法访问父类原型上的属性和方法。

三、组合继承(原型链继承和经典继承的组合)

组合继承是将原型链继承和借用构造函数继承结合使用的方式。通过借用构造函数继承父类的实例属性,通过原型链继承父类的原型属性和方法,从而实现继承。

代码示例:

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;
}

Child.prototype = new Parent();
Child.prototype.constructor = Child;

var child = new Child("child", 18);
child.getName(); // "child"

实现原理:通过在子类构造函数内部通过 call 或 apply 方法调用父类构造函数,从而实现继承父类实例属性。然后将子类原型指向父类的实例,从而实现继承父类原型属性及方法。

优点:既继承了父类构造函数属性,又继承了父类原型上的属性及方法。

缺点:会调用两次父类构造函数,造成内存浪费。

四、原型式继承

原型式继承通过利用一个空对象作为中介实现对对象的复制,从而实现继承。

代码示例:

const parent = {
  name: "parent",
  getName: function () {
    console.log(this.name);
  }
};

const child = Object.create(parent);
child.name = "child";
child.getName(); // "child"

实现原理:通过 Object.create() 方法以一个对象作为参数,创建一个继承自该对象的新对象。

优点:可以实现对某个对象进行简单继承,避免了构造函数和原型的复杂度。

缺点:父类引用类型属性共享给所有子类实例,容易造成意外修改,无法向父类构造函数传递参数。

五、寄生式继承

寄生式继承是在原型式继承的基础上进行了封装,利用一个函数返回一个以父类对象为基础的新对象,实现继承。

代码示例:

const parent = {
  name: "parent",
  getName: function () {
    console.log(this.name);
  }
};

function createChild(parent, name) {
  const child = Object.create(parent);
  child.name = name;
  return child;
}

const child = createChild(parent, "child");
child.getName(); // "child"

实现原理:借助工厂模式的思想,通过一个函数返回一个对象,从而实现继承。

优点:在不需要耦合构造函数的情况下实现继承。

缺点:与构造函数、原型链继承等方式一样,父类引用类型属性共享给所有子类实例,容易造成意外修改,无法向父类构造函数传递参数。

六、寄生组合式继承(最优解)

寄生组合式继承是在组合继承的基础上进行改良,通过寄生式继承来继承父类的原型对象,从而避免了组合继承中调用两次父类构造函数的问题。

代码示例:

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;
}

Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;

var child = new Child("child", 18);
child.getName(); // "child"

实现原理:通过 Object.create() 方法以父类原型对象作为参数,创建一个继承自该对象的新对象,从而避免了调用两次父类构造函数的问题。

优点:避免了调用两次父类构造函数的问题,既继承了父类构造函数属性,又继承了父类原型上的属性及方法。

缺点:代码复杂度较高。

原创文章,作者:UNWVL,如若转载,请注明出处:https://www.506064.com/n/334469.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
UNWVLUNWVL
上一篇 2025-02-05 13:05
下一篇 2025-02-05 13:05

相关推荐

  • 使用JavaScript日期函数掌握时间

    在本文中,我们将深入探讨JavaScript日期函数,并且从多个视角介绍其应用方法和重要性。 一、日期的基本表示与获取 在JavaScript中,使用Date对象来表示日期和时间,…

    编程 2025-04-28
  • JavaScript中使用new Date转换为YYYYMMDD格式

    在JavaScript中,我们通常会使用Date对象来表示日期和时间。当我们需要在网站上显示日期时,很多情况下需要将Date对象转换成YYYYMMDD格式的字符串。下面我们来详细了…

    编程 2025-04-27
  • JavaScript中修改style属性的方法和技巧

    一、基本概念和方法 style属性是JavaScript中一个非常重要的属性,它可以用来控制HTML元素的样式,包括颜色、大小、字体等等。这里介绍一些常用的方法: 1、通过Java…

    编程 2025-04-25
  • Linux sync详解

    一、sync概述 sync是Linux中一个非常重要的命令,它可以将文件系统缓存中的内容,强制写入磁盘中。在执行sync之前,所有的文件系统更新将不会立即写入磁盘,而是先缓存在内存…

    编程 2025-04-25
  • 神经网络代码详解

    神经网络作为一种人工智能技术,被广泛应用于语音识别、图像识别、自然语言处理等领域。而神经网络的模型编写,离不开代码。本文将从多个方面详细阐述神经网络模型编写的代码技术。 一、神经网…

    编程 2025-04-25
  • Linux修改文件名命令详解

    在Linux系统中,修改文件名是一个很常见的操作。Linux提供了多种方式来修改文件名,这篇文章将介绍Linux修改文件名的详细操作。 一、mv命令 mv命令是Linux下的常用命…

    编程 2025-04-25
  • Python安装OS库详解

    一、OS简介 OS库是Python标准库的一部分,它提供了跨平台的操作系统功能,使得Python可以进行文件操作、进程管理、环境变量读取等系统级操作。 OS库中包含了大量的文件和目…

    编程 2025-04-25
  • 详解eclipse设置

    一、安装与基础设置 1、下载eclipse并进行安装。 2、打开eclipse,选择对应的工作空间路径。 File -> Switch Workspace -> [选择…

    编程 2025-04-25
  • MPU6050工作原理详解

    一、什么是MPU6050 MPU6050是一种六轴惯性传感器,能够同时测量加速度和角速度。它由三个传感器组成:一个三轴加速度计和一个三轴陀螺仪。这个组合提供了非常精细的姿态解算,其…

    编程 2025-04-25
  • Java BigDecimal 精度详解

    一、基础概念 Java BigDecimal 是一个用于高精度计算的类。普通的 double 或 float 类型只能精确表示有限的数字,而对于需要高精度计算的场景,BigDeci…

    编程 2025-04-25

发表回复

登录后才能评论