问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

一篇文章弄懂JavaScript的继承方式?

发布网友 发布时间:2024-09-30 11:06

我来回答

1个回答

热心网友 时间:2024-09-30 12:01

JavaScript中的继承方式

学js有一段时间了,但是继承这一块看了好多遍都没有记住,这次看完就索性写篇笔记,加深一下记忆,也可以供大家一起参考学习,有什么错误的地方,感谢大家的指出。?

问:JavaScript中有几种继承方式呢?

?emmm...六种?五种?还是四种来着...

这次记清楚了一共有五种继承方式

盗用构造函数(经典继承方式)

组合继承

原型链式继承

寄生式继承

寄生式组合继承

问:每种继承方式是怎么实现的呢?盗用构造函数

基本思路很简单:在子类构造函数中调用父类构造函数。因为毕竟函数就是在特定上下文中执行代码的简单对象,所以可以使用apply()和call()方法以新创建的对象为上下文执行构造函数。

盗用构造函数的一个优点就是可以在子类构造函数中向父类构造函数传参

function?SuperType(name)?{????this.name?=?name????this.sayName?=?function?()?{????????console.log(this.name);????}}function?SubType(name,?age)?{????//??继承?SuperType?并传参????SuperType.call(this,?name);????//实例属性????this.age?=?age}let?instance1?=?new?SubType('zxc',?2)let?instance2?=?new?SuperType('gyx')//?instance1.sayHi()?//??类也不能访问父类原型上定义的方法,因此所有类型只能使用构造函数模式console.log(instance1);??//?SubType?{?name:?'zxc',?sayName:?[Function?(anonymous)],?age:?2?}组合继承

组合继承(有时候也叫伪经典继承)综合了原型链和盗用构造函数,将两者的优点集中了起来。基本的思路是使用原型链继承原型上的属性和方法,而通过盗用构造函数继承实例属性。这样既可以把方法定义在原型上以实现重用,又可以让每个实例都有自己的属性。

function?SuperType(name)?{????this.name?=?name????this.colors?=?['red',?'blue',?'green']}SuperType.prototype.sayName?=?function?()?{????console.log(this.name);}function?SubType(name,?age)?{????//继承实例属性????SuperType.call(this,?name)????this.age?=?age}//继承原型方法SubType.prototype?=?new?SuperType()?SubType.prototype.sayAge?=?function?()?{????console.log(this.age);}let?instance1?=?new?SubType('zxc',?'22')instance1.sayName()??//zxcinstance1.sayAge()???//?22let?instance2?=?new?SubType("Greg",?27);console.log(instance2.colors);?//?"red,blue,green"instance2.sayName();?//?"Greg";instance2.sayAge();?//?27原型链式继承

原型式继承适用于这种情况:你有一个对象,想在它的基础上再创建一个新对象。你需要把这个对象先传给object(),然后再对返回的对象进行适当修改。

Object.create()方法将原型式继承的概念规范化了这个方法接收两个参数:作为新对象原型的对象,以及给新对象定义额外属性的对象(第二个可选)

let?person?=?{????name:?"Nicholas",????age:?12,????friends:?["Shelby",?"Court",?"Van"]};let?anotherPerson1?=?Object.create(person);anotherPerson1.name?=?'lll'??anotherPerson1.friends.push('zxc')?console.log(anotherPerson1);???//?{?name:?'lll'?}console.log(person.friends);?//[?'Shelby',?'Court',?'Van',?'zxc'?]

//?Object.create()的第二个参数与Object.defineProperties()的第二个参数一样:每个新增属性都通过各自的描述符来描述

let?anotherPerson?=?Object.create(person,?{????name:?{????????value:?"Greg"????}});console.log(anotherPerson.name);?//?"Greg"寄生式继承

寄生式继承背后的思路类似于寄生构造函数和工厂模式:创建一个实现继承的函数,以某种方式增强对象,然后返回这个对象。

function?createAnother(original)?{????//通过调用函数创建一个对象????let?clone?=?Object(original)????clone.sayHi?=?function?()?{?//?以某种方式增强这个对象????????console.log("hi");????};????clone.sayName?=?function?()?{?//?以某种方式增强这个对象????????console.log(this.name);????};????return?clone;?//?返回这个对象}let?person?=?{????name:?"Nicholas",????friends:?["Shelby",?"Court",?"Van"]};let?anotherPerson?=?createAnother(person);anotherPerson.sayHi();?//?"hi"anotherPerson.sayName();?//?"hi"寄生时组合继承function?SuperType(name)?{????this.name?=?name????this.colors?=?['red',?'blue']}SuperType.prototype.sayName?=?function?()?{????console.log(this.name)}function?SubType(name,?age)?{????SuperType.call(this,?name);?//?第二次调用?SuperType()????this.age?=?age;}SubType.prototype?=?new?SuperType();?//?第一次调用?SuperType()SubType.prototype.constructor?=?SubType;SubType.prototype.sayAge?=?function?()?{????console.log(this.age);};let?instance1?=?new?SubType('zxc',?12)console.log(instance1);

在上面的代码执行后,SubType.prototype上会有两个属性:name?和colors。它们都是SuperType的实例属性,但现在成为了SubType的原型属性。在调用SubType构造函数时,也会调用SuperType构造函数,这一次会在新对象上创建实例属性name和colors。这两个实例属性会遮蔽原型上同名的属性。

如图所示,有两组name和colors属性:一组在实例上,另一组在SubType的原型上。这是调用两次SuperType构造函数的结果,好在有办法解决这个问题。

寄生式组合继承通过盗用构造函数继承属性,但使用混合式原型链继承方法。基本思路是不通过调用父类构造函数给子类原型赋值,而是取得父类原型的一个副本。说到底就是使用寄生式继承来继承父类原型,然后将返回的新对象赋值给子类原型。寄生式组合继承的基本模式如下所示:

function?inheritPrototype(subType,?superType)?{????let?prototype?=?object(superType.prototype);?//?创建对象????prototype.constructor?=?subType;?//?增强对象????subType.prototype?=?prototype;?//?赋值对象}

这个inheritPrototype()函数实现了寄生式组合继承的核心逻辑。这个函数接收两个参数:子类构造函数和父类构造函数。在这个函数内部,第一步是创建父类原型的一个副本。然后,给返回的prototype对象设置constructor属性,解决由于重写原型导致默认constructor丢失的问题。最后将新创建的对象赋值给子类型的原型。如下例所示,调用inheritPrototype()就可以实现前面例子中的子类型原型赋值:

function?SuperType(name)?{????this.name?=?name;????this.colors?=?["red",?"blue",?"green"];}SuperType.prototype.sayName?=?function?()?{????console.log(this.name);}function?SubType(name,?age)?{????SuperType.call(this,?name)????this.age?=?age;}inheritPrototype(SubType,?SuperType);SubType.prototype.sayAge?=?function?()?{????console.log(this.age);};

这里只调用了一次SuperType构造函数,避免了SubType.prototype上不必要也用不到的属性,因此可以说这个例子的效率更高。而且,原型链仍然保持不变,因此instanceof操作符和isPrototypeOf()方法正常有效。寄生式组合继承可以算是引用类型继承的最佳模式。

原文:https://juejin.cn/post/7095290456057053191

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
U盘更新专用需要电脑打开怎么让我的U盘和电脑文件夹同步更新啊_百度知 ... 为什么我的硬盘一打开就弹出对话框说选择打开方式. 倒霉的是右键也打... 磁盘右键是打开方式怎么办 我双机盘符总是打开 打开方式 让我选择,右健第一项是打开.不知道是中了... 罗技Lightspeed怎么用? 罗技无线鼠标怎么样?怎么连接电脑使用? 为什么不建议去融资公司上班 融资担保公司一般账务处理及所涉及的会计科目有哪些 月经期间可以游泳吗 经期能不能游泳 JavaScript中6种继承方式及优缺点分析 腾讯在哪找人工服务 中国驻大使是什么意思? ...他对我前所未有的好,这是有什么寓意吗?求解!! ...坐牢。我到处找关系想去看她,但现实里她已经去世三年了 怎么看达达骑手位置 ...的是什么意思?希望大家可以给个详细的答案. 判断题:1.国徽是一个国家的标志。()2.队旗是象征国家的旗帜。()3.中华... 苹果6s的报价 需要上传的照片太大,怎样压缩照片 华为手机为什么不能设置不休眠 荣耀手机无法设置永不休眠 荣耀手机无法设置永不休眠? 支付宝如何开电子发票? 实木复合地板和强化复合地板 到底有什么区别 monkey’s wedding其他地区类似表达 强化地板和实木复合有啥区别 monkey’s wedding释义 我朋友把我的好友给改了,我想改成别的请问在手机上怎么改这个? 我的手机键盘以前设置了密码,改过,后来忘了,现在我想改掉原来密码,我应 ... js原生语法之prototype,__proto__和constructor 从天津机场出来怎么走到678车站 从天津滨海机场下了飞机怎么走能到机场巴士站(678终点站)? icloud照片库关闭后怎么恢复 梦见妈妈住在一间简陋的出租屋里,不清楚是不是因为跟爸爸吵架了... ...俗语“人穷莫说三句话,没钱少管三件事”有道理吗?到底是啥意思呢... ps漫画效果怎么做ps漫画效果怎么做出来的 萧蕊冰:用ps怎么做出漫画效果 漫画效果使用PS制作二次元动漫效果 手机哪些地图导航好用? ...科兴和北京生物疫苗可以混打吗打两针北京生物后能打科兴疫苗加强针吗... 违章缴费单丢了怎么办? ...斗地方在后台运行,但还是提示正在后台运行怎么回事? 为什么脚会酸酸的味道 为什么脚会有酸酸的味道 湿苞菠萝蜜怎么看熟没熟湿苞菠萝蜜如何看熟没熟 在哪可以查询欧米茄手表的编号? 欧米茄手表序列号查询系统 我在昆山某电子厂工作一年多了,公司如果倒闭是不是应该给与员工赔偿 ...音乐家菅野洋子负责制作的-B站硬核会员2022年答案大全