面试题: 对象继承的方式有哪些

在 JavaScript 中,对象继承可以通过多种方式实现。每种方法都有其特点和适用场景。以下是几种常见的对象继承方式:

1. 原型链继承(Prototype Chain Inheritance)

这是最基础的对象继承方式,利用了 JavaScript 的原型机制。每个对象都有一个内部属性 [[Prototype]],它指向另一个对象,即该对象的原型。当尝试访问一个对象的属性时,如果对象本身没有这个属性,JavaScript 引擎会沿着原型链向上查找,直到找到该属性或到达原型链的末端(通常是 Object.prototype)。

function Parent() {this.name = 'parent';
}Parent.prototype.sayHello = function() {console.log('Hello from ' + this.name);
};function Child() {}// 设置 Child 的 prototype 为 Parent 的实例
Child.prototype = new Parent();
Child.prototype.constructor = Child; // 修复构造函数指针const child = new Child();
child.sayHello(); // 输出: Hello from parent

缺点:所有子类实例共享同一个父类实例的属性,可能会导致意外的状态共享问题。

2. 构造函数继承(Constructor Function Inheritance)

通过使用 callapply 方法,可以在子类构造函数中调用父类构造函数,从而将父类的属性复制到子类实例上。这种方式可以避免原型链继承中的状态共享问题。

function Parent(name) {this.name = name;
}Parent.prototype.sayHello = function() {console.log('Hello from ' + this.name);
};function Child(name, age) {Parent.call(this, name); // 调用父类构造函数this.age = age;
}const child = new Child('child', 10);
console.log(child.name); // 输出: child
console.log(child.age);  // 输出: 10

缺点:子类不能继承父类的原型方法,需要额外的方法来继承这些方法。

3. 组合继承(Combination Inheritance)

组合继承结合了原型链继承和构造函数继承的优点,既可以通过构造函数继承父类的属性,又可以通过原型链继承父类的方法。

function Parent(name) {this.name = name;this.colors = ['red', 'blue'];
}Parent.prototype.sayHello = function() {console.log('Hello from ' + this.name);
};function Child(name, age) {Parent.call(this, name); // 第一次调用 Parentthis.age = age;
}Child.prototype = new Parent(); // 第二次调用 Parent
Child.prototype.constructor = Child;const child1 = new Child('child1', 10);
const child2 = new Child('child2', 20);child1.colors.push('green');
console.log(child1.colors); // 输出: ['red', 'blue', 'green']
console.log(child2.colors); // 输出: ['red', 'blue']

缺点:两次调用父类构造函数,第一次是在创建子类实例时,第二次是在设置子类原型时,这可能会造成不必要的开销。

4. 原型式继承(Prototypal Inheritance)

这种继承方式不依赖于构造函数,而是直接基于对象创建新的对象。通常使用 Object.create() 方法来实现。

const parent = {name: 'parent',sayHello: function() {console.log('Hello from ' + this.name);}
};const child = Object.create(parent);
child.name = 'child';child.sayHello(); // 输出: Hello from child

优点:简单明了,适合不需要复杂构造函数的情况。

5. 寄生式继承(Parasitic Inheritance)

寄生式继承是原型式继承的增强版,它在创建新对象的基础上,进一步增强对象的功能,然后再返回这个对象。

function createChild(parent) {const child = Object.create(parent); // 使用原型式继承child.sayHi = function() {console.log('Hi from ' + this.name);};return child;
}const parent = {name: 'parent',sayHello: function() {console.log('Hello from ' + this.name);}
};const child = createChild(parent);
child.name = 'child';
child.sayHi(); // 输出: Hi from child

优点:可以自由地添加或修改对象的功能。

6. 寄生组合式继承(Parasitic Combination Inheritance)

寄生组合式继承是组合继承的优化版本,它只调用一次父类构造函数,避免了组合继承中的效率问题。这是目前最常用的继承模式之一。

function inheritPrototype(child, parent) {const prototype = Object.create(parent.prototype); // 创建父类原型的副本prototype.constructor = child; // 修正构造函数指针child.prototype = prototype;   // 将副本赋值给子类的原型
}function Parent(name) {this.name = name;this.colors = ['red', 'blue'];
}Parent.prototype.sayHello = function() {console.log('Hello from ' + this.name);
};function Child(name, age) {Parent.call(this, name); // 只调用一次 Parentthis.age = age;
}inheritPrototype(Child, Parent);const child1 = new Child('child1', 10);
const child2 = new Child('child2', 20);child1.colors.push('green');
console.log(child1.colors); // 输出: ['red', 'blue', 'green']
console.log(child2.colors); // 输出: ['red', 'blue']

优点:只调用一次父类构造函数,避免了重复调用的问题,同时保持了组合继承的优点。

7. 类(Class)继承(ES6+)

ES6 引入了 class 语法糖,使得继承更加简洁和直观。实际上,class 仍然是基于原型的,但它提供了一种更接近传统面向对象语言的语法。

class Parent {constructor(name) {this.name = name;}sayHello() {console.log('Hello from ' + this.name);}
}class Child extends Parent {constructor(name, age) {super(name); // 调用父类构造函数this.age = age;}sayAge() {console.log('I am ' + this.age + ' years old.');}
}const child = new Child('child', 10);
child.sayHello(); // 输出: Hello from child
child.sayAge();   // 输出: I am 10 years old.

优点:语法简洁,易于理解和使用,特别适合面向对象编程。

总结

  • 原型链继承 是最基础的继承方式,但存在状态共享的问题。
  • 构造函数继承 解决了状态共享问题,但无法继承原型方法。
  • 组合继承 结合了两者的优势,但有重复调用父类构造函数的缺点。
  • 原型式继承寄生式继承 更加灵活,适用于不需要复杂构造函数的场景。
  • 寄生组合式继承 是组合继承的优化版本,解决了重复调用的问题,是最推荐的继承方式之一。
  • 类继承 提供了更简洁的语法,适合现代 JavaScript 开发。

选择哪种继承方式取决于具体的需求和项目背景。对于新项目,特别是使用 ES6+ 的项目,推荐使用 class 语法糖来实现继承,因为它不仅语法简洁,而且社区支持广泛。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/66489.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

React路由拦截器详解

在React中&#xff0c;路由拦截器是一种机制&#xff0c;用于在导航到特定路由之前执行一些逻辑&#xff0c;比如权限校验、用户认证或动态路由控制。通常&#xff0c;React使用react-router-dom库来管理路由&#xff0c;通过<Routes>和<Route>定义路由规则。 实现…

力扣经典题目之219. 存在重复元素 II

今天继续给大家分享一道力扣的做题心得今天这道题目是 219. 存在重复元素 II&#xff0c;我使用 hashmap 的方法来解题 题目如下&#xff0c;题目链接&#xff1a;219. 存在重复元素 II 1&#xff0c;题目分析 此题目给我们了一个整数数组 nums 和一个整数 k &#xff0c;需要…

四、VSCODE 使用GIT插件

VSCODE 使用GIT插件 一下载git插件与git Graph插件二、git插件使用三、文件提交到远程仓库四、git Graph插件 一下载git插件与git Graph插件 二、git插件使用 git插件一般VSCode自带了git&#xff0c;就是左边栏目的图标 在下载git软件后vscode的git插件会自动识别当前项目 …

消息队列MQ(二)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 MQ学习笔记 前言一、发送者的可靠性1. 生产者重试机制2. 生产者确认机制3. 实现生产者确认 二、MQ的可靠性1. 数据持久化2. LazyQueue 前言 在用MQ实现异步调用时&#xff0…

docker 常用命令实践DEMO

1.1 docker run -d -p 8080:80 --name web_server nginx 命令的详细解读 docker run: 这是 Docker 的一个基本命令&#xff0c;用于从指定的镜像启动一个新的容器。 -d: 这个参数是 --detach 的简写&#xff0c;意味着容器将在后台运行。也就是说&#xff0c;命令会立即返回&a…

Ubuntu18.04离线安装audit

Ubuntu18.04离线安装audit 查看ubuntu系统版本 lsb_release -a安装版本 下载地址 https://launchpad.net/ubuntu/bionic/arm64/libauparse0/1:2.8.2-1ubuntu1.1 https://launchpad.net/ubuntu/bionic/arm64/auditd/1:2.8.2-1ubuntu1 sudo dpkg -i libauparse0_2.8.2-1ubunt…

Meilisearch ASP.Net Core API 功能demo

安装 MeiliSearch 0.15.5 0.15.5demo code using Meilisearch; using System.Data; using System.Text.Json; using System.Text.Json.Serialization;namespace MeiliSearchAPI {public class MeilisearchHelper{public MeilisearchHelper(){DefaultClient…

关于element自定义样式popper-class

当我们在使用element组件时&#xff0c;会遇到需要修改组件的样式&#xff0c;但是样式无法覆盖原样式的情况。 用popper-class属性&#xff0c;给组件传递样式&#xff0c; 原理&#xff1a;其实就是传递给组件一个class名&#xff0c;然后设置class的样式&#xff0c;所以自定…

2024.1.5总结

今日不开心:这周本来想花点时间学习的&#xff0c;没想到全都花在刷视频&#xff0c;外出消费去了。 今日思考: 1.找对象这件事确实不能强求&#xff0c;顺其自然吧&#xff0c;单身和不单身&#xff0c;其实&#xff0c;各有各的利弊。在一次坐地铁的过程中&#xff0c;我一…

数据分析思维(九):分析方法——AARRR模型分析方法

数据分析并非只是简单的数据分析工具三板斧——Excel、SQL、Python&#xff0c;更重要的是数据分析思维。没有数据分析思维和业务知识&#xff0c;就算拿到一堆数据&#xff0c;也不知道如何下手。 推荐书本《数据分析思维——分析方法和业务知识》&#xff0c;本文内容就是提取…

【计算机网络】课程 实验四 配置快速生成树协议(RSTP)

实验四 配置快速生成树协议&#xff08;RSTP&#xff09; 一、实验目的 1&#xff0e;理解快速生成树协议RSTP的工作原理。 2&#xff0e;掌握如何在交换机上配置快速生成树。 二、实验分析与设计 【背景描述】 某学校为了开展计算机教学和网络办公&#xff0c;建立了一个计…

Tauri教程-基础篇-第一节 Tauri项目创建及结构说明

“如果结果不如你所愿&#xff0c;就在尘埃落定前奋力一搏。”——《夏目友人帐》 “有些事不是看到了希望才去坚持&#xff0c;而是因为坚持才会看到希望。”——《十宗罪》 “维持现状意味着空耗你的努力和生命。”——纪伯伦 Tauri 技术教程 * 第四章 Tauri的基础教程 第一节…

【Docker项目实战】使用Docker部署Typemill轻量级平面文件CMS

【Docker项目实战】使用Docker部署Typemill轻量级平面文件CMS 一、Typemill介绍1.1 Typemill简介1.2 主要特点1.3 主要使用场景二、本次实践规划2.1 本地环境规划2.2 本次实践介绍三、本地环境检查3.1 检查Docker服务状态3.2 检查Docker版本3.3 检查docker compose 版本四、下载…

pyinstaller冻结打包多进程程序的bug:无限创建进程直至系统崩溃

前面写过两篇相关的文章&#xff1a; PyQt应用程序打包Python自动按键 这两篇文章都没有提到下面的这个重要问题&#xff1a; 采用Pyinstaller冻结打包多进程程序时&#xff0c;必须非常小心。这个技术线在Windows上会有一个非常严重的Bug。直接运行打包后的程序会造成无限创…

网络安全-kail linux 网络配置(基础篇)

一、网络配置 1.查看网络IP地址&#xff0c; 我的kail&#xff1a;192.168.15.128 使用ifconfig查看kail网络连接情况&#xff0c;ip地址情况 又复制了一台kail计算机的IP地址。 再看一下windows本机&#xff1a;使用ipconfig进行查看&#xff1a; 再看一下虚拟机上的win7I…

window.open 被浏览器拦截解决方案

前言 在项目开发中&#xff0c;点击支付按钮后需要发送支付请求&#xff0c;并在请求完成后的回调中&#xff0c;经过一系列判断&#xff0c;符合某种条件下弹出一个新窗口页面。自然想到使用 window.open&#xff0c;但发现该操作会被浏览器拦截。 分析原因 当浏览器检测到…

uni app 写的 小游戏,文字拼图?文字拼写?不知道叫啥

从下方的偏旁部首中选在1--3个组成上面文章中的文字&#xff0c;完成的文字标红 不喜勿喷 《满江红》 其中用到了两个文件 strdata.json parameters.json 这两个文件太大 放到资源中了 资源文件 <template><view class"wenzi_page_main"><view c…

qt编译环境异常问题解决一例

编译程序提示错误信息&#xff1a; dependent ..\..\..\..\..\..\src\vcpkg\installed\x64-windows\include\qt5\QtCore\QRunnable does not exist 具体找不到哪个类就看你的代码具体要include哪个头文件是第一个&#xff0c;也有可能是提示找不到QMainWindow&#xff0c;总…

分享几个高清无水印国外视频素材网站

在数字内容创作日益盛行的今天&#xff0c;高质量的视频素材成为了视频制作、广告创意和多媒体项目中不可或缺的元素。对于追求专业水准的创作者而言&#xff0c;高清、无水印的视频素材是确保作品质量的基石。以下将分享几个优质的视频素材网站&#xff0c;为您的创作之路提供…

【LLM】大语言模型基础知识及主要类别架构

文章目录 LLM大语言模型1.LLM基础知识1.1大模型介绍:1.2语言模型1.21n-gram语言模型1.22神经网络语言模型1.23基于Transformer的预训练语言模型1.24大语言模型 1.3模型评估指标1.31 BLEU1.32 Rouge指标1.33 困惑度PPL 2.LLM主要类别架构2.1 自编码模型2.2 自回归模型2.3 Encode…