当前位置: 首页 > news >正文

大白话JavaScript详细描述基于原型链实现对象继承的步骤,分析其在共享属性、内存占用等方面的优缺点

大白话JavaScript详细描述基于原型链实现对象继承的步骤,分析其在共享属性、内存占用等方面的优缺点

在 JavaScript 里,基于原型链实现对象继承是一种常用的继承方式。下面咱们详细说说步骤,还会加上代码注释来辅助理解。

步骤 1:创建父对象构造函数
// 定义一个名为 Parent 的构造函数,用于创建父对象
function Parent() {
    // 给父对象添加一个属性 name,值为 'Parent'
    this.name = 'Parent';
    // 给父对象添加一个方法 sayName,用于打印 name 属性的值
    this.sayName = function() {
        console.log(this.name);
    };
}

这里我们定义了一个 Parent 构造函数,它就像是一个生产父对象的“模板”。每个通过 new Parent() 创建的对象都会有 name 属性和 sayName 方法。

步骤 2:创建子对象构造函数
// 定义一个名为 Child 的构造函数,用于创建子对象
function Child() {
    // 给子对象添加一个属性 age,值为 10
    this.age = 10;
}

Child 构造函数是生产子对象的“模板”,每个通过 new Child() 创建的对象都会有 age 属性。

步骤 3:设置原型链实现继承
// 将 Child 构造函数的原型指向 Parent 的一个实例
// 这样 Child 创建的对象就可以通过原型链访问 Parent 的属性和方法
Child.prototype = new Parent();

这一步是关键,我们把 Child 构造函数的 prototype 属性设置为 Parent 的一个实例。这就好比给 Child 对象们建了一条“通道”,通过这条“通道”,它们能访问到 Parent 对象的属性和方法。

步骤 4:创建子对象实例并测试继承
// 创建一个 Child 的实例 child
let child = new Child();
// 调用子对象继承自父对象的 sayName 方法
child.sayName(); 
// 输出子对象自身的 age 属性
console.log(child.age); 

现在我们创建了一个 Child 的实例 child,因为前面设置了原型链,所以 child 可以调用 ParentsayName 方法,同时也有自己的 age 属性。

基于原型链实现对象继承的优缺点

优点
  • 共享属性和方法:通过原型链,多个子对象可以共享父对象的属性和方法。这就好比一群人共用一个仓库里的东西,节省了资源。比如上面的例子中,所有 Child 实例都可以共享 ParentsayName 方法,不需要每个实例都单独保存一份这个方法,减少了内存占用。
// 创建两个 Child 实例
let child1 = new Child();
let child2 = new Child();
// 这两个实例的 sayName 方法是同一个,说明它们共享了这个方法
console.log(child1.sayName === child2.sayName); 
  • 代码复用:可以复用父对象的代码,避免重复编写相同的属性和方法。这就像搭积木,我们可以把已经搭好的一部分积木(父对象的代码)直接拿过来用,加快开发速度。
缺点
  • 内存占用问题:虽然共享属性和方法能节省一些内存,但如果父对象的属性是引用类型(比如数组、对象),当一个子对象修改了这些引用类型的属性时,会影响到其他所有子对象。因为它们共享的是同一个引用。
// 修改 Parent 构造函数,添加一个引用类型的属性 hobbies
function Parent() {
    this.name = 'Parent';
    this.sayName = function() {
        console.log(this.name);
    };
    // 添加一个引用类型的属性 hobbies,初始值是一个数组
    this.hobbies = ['reading'];
}
// 重新设置原型链
Child.prototype = new Parent();
// 创建两个 Child 实例
let child1 = new Child();
let child2 = new Child();
// child1 修改了 hobbies 属性
child1.hobbies.push('swimming');
// child2 的 hobbies 属性也被改变了,因为它们共享同一个引用
console.log(child2.hobbies); 
  • 初始化问题:在创建子对象时,无法向父对象的构造函数传递参数。这就像我们造一个东西,没办法在造的时候给它的“模板”传递一些特定的信息,灵活性不够。
// 假设我们想在创建 Child 实例时给 Parent 的构造函数传递参数,下面这样是做不到的
// 因为 Child 的原型已经固定是 new Parent() 了,没办法再传参数
let child = new Child(); 

综上所述,基于原型链实现对象继承有它的好处,比如共享属性和代码复用,但也存在一些问题,像内存管理和初始化灵活性方面的不足。在实际开发中,要根据具体需求来选择合适的继承方式。

基于原型链实现对象继承有哪些潜在的问题或风险?

基于原型链实现对象继承存在以下一些潜在问题或风险:

  • 意外修改共享属性:原型链上的属性是共享的,这可能导致意外的副作用。如果一个实例修改了原型链上的属性,那么所有继承该原型的实例都会受到影响。特别是对于引用类型的属性,如对象或数组,一个实例对其进行修改,会影响到其他所有实例。
  • 原型污染:由于原型链的开放性,可能会意外地修改原型对象,导致所有继承该原型的对象都受到影响。这种情况被称为原型污染,可能会引入难以发现的错误。
  • 实例与原型的强耦合:基于原型链的继承使得实例与原型之间存在紧密的耦合关系。如果修改了原型对象,可能会对所有相关的实例产生不可预测的影响,这使得代码的维护和理解变得困难。
  • 无法向父构造函数传参:在基于原型链实现对象继承时,无法在创建子对象时向父对象的构造函数传递参数,这限制了对象的初始化方式,降低了代码的灵活性。
  • 继承关系复杂时难以维护:当原型链层次较深或继承关系复杂时,代码的可读性和可维护性会显著下降。追踪属性和方法的来源变得困难,调试也会变得更加复杂。
  • 不支持多继承:JavaScript的原型链继承本质上是单继承,一个对象只能有一个直接的原型。如果需要实现多继承,基于原型链的方式会变得复杂且不直观,可能需要额外的代码来模拟多继承的行为。

相关文章:

  • OpenHands:OpenDevin的升级版,由人工智能驱动的软件开发代理平台
  • stm32第四天控制蜂鸣器
  • mmdet3d.models.utils的clip_sigmoid理解
  • 【实战ES】实战 Elasticsearch:快速上手与深度实践-8.1.1基于ES的语义搜索(BERT嵌入向量)
  • Chainlit 实现SSO单点登录CAS授权完整代码图文教程
  • Python:被装饰的函数,多个装饰器的装饰过程
  • html css 笔记
  • 什么是设计模式
  • Matlab 双线性插值(二维)
  • TypeScript基础
  • Uniapp使用地图的时候滑动上层的view地图也滑动
  • 【DevOps】Backstage介绍及如何在Azure Kubernetes Service上进行部署
  • 附下载 | 2024 OWASP Top 10 基础设施安全风险.pdf
  • Shader中着色器的编译目标级别
  • vue3数据双向绑定解析
  • Unity3D 着色器优化(Shader Optimization)
  • 机器人基础知识
  • 如何设置GET请求的参数?
  • SAP SD学习笔记31 - 销售BOM
  • Java基础入门流程控制全解析:分支、循环与随机数实战
  • 比特币价格时隔三个月再度站上10万美元
  • 经济日报整版聚焦“妈妈岗”:就业路越走越宽,有温度重实效
  • 中信银行:拟出资100亿元全资设立信银金融资产投资有限公司
  • 谜语的强制力:弗洛伊德与俄狄浦斯
  • 中科院院士魏辅文已卸任江西农业大学校长
  • 上海:5月8日起5年以上首套个人住房公积金贷款利率下调至2.6%