最新要闻
- 焦点速讯:五一期间 市公交公司安全运送乘客48万余人次
- 微信2023五一大数据来了!十大景区花钱榜公布 你花了多少钱? 观焦点
- 《流浪地球》剧情成真!科学家首次观测到一颗行星被恒星吞噬 世界热门
- 每日观点:今年还有调休假:中秋国庆假期后要连上7天班!
- 全球新消息丨最新研究:外星人或利用手机信号绘制出地球地图
- 震撼!恒星吞噬行星全过程首次曝光 地球:我命休矣?
- 林志玲出席活动被问二胎做出回应称自己不会要二胎,一个就满足了
- 世界快看:电动车降价彻底无望?今日电池级碳酸锂涨价5000元/吨
- 骁龙8+待机47.9天如何实现?小米平板6系列“深度休眠”官方揭秘
- 【世界新视野】多样性算力推委会正式成立,透露哪些重要信号?
- 五一假期,江门水路发送旅客超15万人次 世界快报
- 信息:2022年跨境电商市场规模15.7万亿元
- 【环球时快讯】6499元买吗?雷军晒小米13 Ultra限量定制色真机上手图:网友大呼背刺
- 家用强力灭蚊!雅格充电电蚊拍10.9元起狂促_报资讯
- 世界聚焦:“五一”假期日均125.3万人次出入境
- 奈雪五一小长假订单同比上涨120% 部分门店涨幅超800%|热资讯
手机
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
记录-对象有哪些继承方式_信息
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助
1. 原型链
温故而知新:
构造函数、原型和实例的关系: 每个构造函数都有一个原型对象,原型有一个属性指回构造函数,实例有一个内部指针指向原型。
【资料图】
思考:如果原型是另一个类型的实例呢? 那就意味着这个原型本身有一个内部指针指向另一个原型,相应的另一个原型也有一个指针指向另一个构造函数。这样就在实例和原型之间构造了一条原型链。这就是原型链的基本思想。实现原型链涉及如下代码模式:
function SuperType(){ this.property = true;}SuperType.prototype.getSuperValue = function(){ return this.property;}function SubType(){ this.subproperty = false;}// 继承SuperTypeSubType.prototype = new SuperType()SubType.prototype.getSubValue = function(){ return this.subproperty;}let instance = new SubType()console.log(instance.getSuperValue()); //true
以上的代码定义了两个类型:SuperType和SubType。这两个类型分别定义了一个属性和方法。两个类型的主要区别是:SubType通过创建SuperType的实例并将其赋值给自己的原型SubType.prototype实现了对SuperType的继承。这个赋值重写了SubType最初的原型,将其替换成SuperType的实例。这意味着SuperType实例可以访问的所有属性和方法也会存在于SubType.prototype。这样实现继承后,紧接着又给SuperType的实例添加了一个新的方法。最后又创建了SubType的实例并调用了它继承的getSuperValue方法。
默认原型
默认情况下,所有引用类型都继承自Object,这也是通过原型链实现的。任何函数默认的原型都是一个Object的实例,这意味着这个实例有一个内部指针指向Object.prototype。这也是为什么自定义类型能够继承包括toString()、valueOf在内部的所有默认方法的原因。 SubType继承SuperType,而SuperType继承Object。在调用instance.toString时,实际上调用的是保存在Object.prototype上的方法。
原型与继承的关系
原型与继承的关系可以通过两种方式来确定:
使用instanceof操作符:
如果一个实例的原型中出现过相应的构造函数,则instanceof返回true
console.log(instance instanceof Object); //true console.log(instance instanceof SuperType); //true console.log(instance instanceof SubType); //true
从技术上讲,instance是Object、SuperType、SubType的实例,因为instance的原型链中包含这些构造函数的原型。结果就是instanceof对所有这些构造函数都返回true。
使用isPrototypeOf()方法
原型链中的每个原型都可以调用这个方法,这要原型链中包含这个原型,这个方法就会返回true
console.log(Object.prototype.isPrototypeOf(instance)); //true console.log(SuperType.prototype.isPrototypeOf(instance)); //true console.log(SubType.prototype.isPrototypeOf(instance)); //true
关于方法
子类有时需要覆盖父类的方法,或者增加父类没有的方法。为此,这些方法必须在原型赋值之后再添加到原型上。来看下面的例子:
function SuperType(){ this.property = true;}SuperType.prototype.getSuperValue = function(){ return this.property;}function SubType(){ this.subproperty = false;}// 继承SuperTypeSubType.prototype = new SuperType()// 新方法 SubType.prototype.getSubValue = function(){ return this.subproperty;}// 覆盖已有的方法SubType.prototype.getSuperValue = function(){ return false;}let instance = new SubType()console.log(instance.getSuperValue()); //false
以上代码新增两个方法。第一个方法getSubValue()是SubType的新方法。而第二个方法getSuperValue()是原型链上已经存在但在这里被遮蔽的方法。;后面在SubType实例上调用getSuperValue()时调用的是这个方法。而SuperValue的实例仍然会调用最初的方法。重点在于上述两个方法都是在把原型赋值为SuperType的实例之后定义的。 另一个要理解的重点,以对象字面量方式创建原型方法,会破环之前的原型链。因为这样相当于重写原型链。
function SuperType(){ this.property = true; } SuperType.prototype.getSuperValue = function(){ return this.property; } function SubType(){ this.subproperty = false; } // 继承SuperType SubType.prototype = new SuperType() // 通过对象字面量添加新的方法,会导致上一行无效 SubType.prototype = { getSubValue(){ return this.subproperty; }, someOtherMethod(){ return false; } } let instance = new SubType() console.log(instance.getSuperValue()); //instance.getSuperValue is not a function
子类的原型在被赋值为SuperType的实例后,又被一个对象字面量覆盖了。覆盖后的原型是一个Object的实例,而不再是SuperType的实例。因此,之前的原型链就断了。SubType和SuperType之间也没有关系了。
原型链的额问题
原先的实例属性变成了原型属性 原型包含的引用值会在所有实例间共享,在使用原型实现继承时,原型实际上变成了另一个类型的实例。
function SuperType(){ this.colors= ["red","blue","green"] } function SubType() { } // 继承SuperType SubType.prototype = new SuperType() let instance1 = new SubType() instance1.colors.push("black"); console.log(instance1.colors); //["red", "blue", "green", "black"] let instance2 = new SubType() console.log(instance2.colors); //["red", "blue", "green", "black"]
SuperType构造函数定义了一个colors属性,其中包含一个数组(引用值)。每个SuperType的实例都会有自己的colors属性,包含自己的数组。但是当SubType通过原型继承SuperType后,SubType.prototype变成了SuperType的一个实例,因而也获得了自己的colors属性。这类似于创建了SubType.prototype.colors属性。最终结果是,SubType的所有实例都会共享这个colors属性。这一点通过instance1.colors上的属性也能反应到instance2.colors上就可以看出。
子类型在实例化时不能给夫类型的构造函数传参 我们无法在不影响所有对象实例的情况下把参数传进父类的构造函数。再加上原型中包含引用值的问题,就导致原型链基本不会被单独使用。
2. 盗用构造函数
盗用构造函数是用来解决原型包含引用值导致的继承问题。基本思路:在子类构造函数中调用父类构造函数。因为函数是在特定上下文中执行代码的简单对象,所以可以使用apply()和call()方法以新创建的对象上下文执行构造函数。
function SuperType(){ this.colors = ["red","blue","green"];}function SubType(){ // 继承SuperType /* *********** */ SuperType.call(this); /* *********** */}let instance1 = new SubType();instance1.colors.push("black");console.log(instance1.colors); // ["red", "blue", "green", "black"]let instance2 = new SubType()console.log(instance2.colors); //["red", "blue", "green"]
以上代码展示了盗用构造函数的调用。通过使用call()或者apply()方法,SuperType构造函数在为SubType的实例创建的新对象的上下文中执行了。这相当于新的SubType对象上运行了SuperType函数中的所有初始化代码。结果就是每个实例都会有自己的colors属性。
1. 优点
可以在子类构造函数中向父类构造函数传参
function SuperType(name){ this.name = name;}function SubType(){ // 继承SuperType并传参 SuperType.call(this,"Nicholas"); // 实例属性 this.age = 29}let instance = new SubType()console.log(instance.name); //Nicholasconsole.log(instance.age); //29
SuperType构造函数接受一个参数name,然后将它赋值给一个属性。在SubType构造函数中调用SuperType构造函数时传入这个参数,实际上会在SubType的实例上定义name属性。为确保SuperType构造函数不会覆盖SubType定义的属性,可以在调用父类构造函数之后再给子类实例添加额外的属性。
2. 缺点
必须在构造函数中定义方法,因此函数不能重用。子类不能访问父类原型上定义的方法,因此所有类型只能使用构造函数模式。由于存在以上问题,所以盗用构造函数基本上也不能单独使用。
3. 组合继承
组合继承也叫伪经典继承,综合了原型链和盗用构造函数,将两者的优点集中起来。基本思路是:使用原型链继承原型上的属性和方法,通过盗用构造函数继承实例属性。这样既可以把方法定义在原型上以实现重用,又可以让每个实例都有自己的属性。
/* 组合继承 */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("Nicholas",29)instance1.colors.push("blcak");console.log(instance1.colors); //["red", "blue", "green", "blcak"]instance1.sayName() //Nicholasinstance1.sayAge(); //29let instance2 = new SubType("Greg",27)console.log(instance2.colors); //["red", "blue", "green"]instance2.sayName(); //Greginstance2.sayAge(); //27
SuperType构造函数定义了两个属性name和colors,而它的原型上也定义了一个方法叫sayName()。SubType构造函数调用了SuperType构造函数,传入name参数,然后又定义了自己的属性age。此外,SubType.prototype也被赋值为SuperType的实例。原型赋值之后,又在这个原型上添加了新方法sayAge()。这样就可以创建两个SubType实例,让这两个实例都有自己的属性,包括colors,同时还共享相同的方法。 组合继承弥补了原型链和盗用构造函数的不足,是JavaScript中使用最多的继承模式。而且组合继承也保留了instanceof操作符和isPrototypeOf()方法识别合成对象的能力。缺点: 父类构造函数会被调用两次,一次是在创建子类原型时调用,一次是在子类构造函数中调用。 本质上,子类原型最终是要包含超类对象的所有实例属性,子类构造函数只要在执行时重写自己的原型就行了。
4. 原型式继承
2006年Douglas Crockford的文章:《JavaScript中的原型式继承》中介绍了一种不涉及严格意义上构造函数的继承方法。作者的出发点是即使不自定义类型也可以通过原型实现对象之间的信息共享。文章给出了一个函数:
function object(o){ function F(){} F.prototype = o; return new F()}
这个object
方法会创建一个临时构造函数,将传入的对象赋值给这个构造函数的原型,然后返回这个临时类型的一个实例。本质上,object()
是对传入对象执行了一次浅复制。
function object(o){ function F(){} F.prototype = o; return new F()}let person = { name:"Nicholas", friends:["Shelby","Court","Van"]};let anotherPerson = object(person);anotherPerson.name = "Greg";anotherPerson.friends.push("Rob");let yetAnotherPerson = object(person);yetAnotherPerson.name = "Linda";yetAnotherPerson.friends.push("Barbie")console.log(person.friends); //["Shelby", "Court", "Van", "Rob", "Barbie"]
ECMAScript
通过增加Object.create()
方法将原型式继承的概念规范化。这个方法接受两个参数:作为新对象原型的对象,给新对象定义额外属性的对象(可选)。在只有一个参数时,Object.create()
与这里的object()
方法效果类似。
let person = { name:"Nicholas", friends:["Shelby","Court","Van"]}let anotherPerson = Object.create(person);anotherPerson.name = "Greg";anotherPerson.friends.push("Rob");let yetAnotherPerson = Object.create(person);yetAnotherPerson.name = "Linda"yetAnotherPerson.friends.push("Barbie")console.log(person.friends); //["Shelby", "Court", "Van", "Rob", "Barbie"]
Object.create()
的第二个参数与Object.defineProperties()
的第二个参数一样:每个新增参数属性都通过各自的描述符来描述。以这种方式添加的属性会遮蔽原型对象上的同名属性。
let person = { name:"Nicholas", friends:["Shelby","Court","Van"]}let anotherPerson = Object.create(person,{ name:{ value:"Greg" }});console.log(anotherPerson.name); //Greg
原型式继承非常适合不需要单独创建构造函数,但仍然需要在对象间共享信息的场合。但要记住,属性中包含的引用值始终会在相关对象间共享,跟使用原型模式时一样的。
5. 寄生式继承
寄生式继承背后的思路类似于寄生构造函数和工厂模式:创建一个实现继承的函数,以某种方式增强对象,然后返回这个对象。基本的寄生继承模式如下:
function createAnother(original){ let clone = object(original); //通过调用函数创建一个新对象 clone.sayHi = function(){ //以某种方式增强这个对象 console.log("HI"); }; return clone; //返沪这个对象}
createAnother()
函数接受一个参数,就是新对象的基准对象。这个对象original
会被传给object()
函数,然后将返回的新对象赋值给clone
对象添加一个新方法sayHi()
。最后返回这个对象。
function object(o){ function F(){} F.prototype = o; return new F()}function createAnother(original){ let clone = object(original); //通过调用函数创建一个新对象 clone.sayHi = function(){ //以某种方式增强这个对象 console.log("Hi"); }; return clone; //返沪这个对象}let person = { name:"Nicholas", friends:["Shelby","Court","Van"]}let anotherPerson = createAnother(person);anotherPerson.sayHi(); //Hi
这个例子基于person对象返回了一个新对象。新返回的anotherPerson对象具有person的所有属性和方法,还有一个新方法叫sayHi() 寄生式继承同样适合主要关注对象,而不在乎类型和构造函数的场景。object()函数不是寄生式继承所必需的,任何返回新对象的函数都可以在这里使用。==注意:==通过寄生式继承给对象添加函数会导致函数难以重用,与构造函数模式类似。
6. 寄生式组合继承
通过盗用构造函数继承属性,但使用混合式原型链继承方法。基本思路是不通过调用父类构造函数给子类原型赋值,而实取得父类原型的一个副本。说到底就是使用寄生式继承来继承父类原型,然后将返回的新对象赋值给子类原型。
function inheritPrototype(subType,superType){ let prototype = object(superType.prototype); //创建对象 prototype.constructor = subType; //增强对象 subType.prototype = prototype; //赋值对象}
这个inheritPrototype()函数实现了寄生式组合继承的核心逻辑。这个函数接受到两个参数:子类构造函数和父类构造函数。这个函数内部,第一步是创建一个父类原型的一个副本。然后,给返回的prototype对象设置constructor属性,解决由于重写原型导致默认constructor丢失的问题。最后将新创建的对象赋值给子类型的原型。调用inheritPrototype()就可以实现前面例子中的子类型原型赋值:
function object(o){ function F(){} F.prototype = o; return new F()}function inheritPrototype(subType,superType){ let prototype = object(superType.prototype); //创建对象 prototype.constructor = subType; //增强对象 subType.prototype = prototype; //赋值对象}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://blog.csdn.net/qq_39200185/article/details/115134869
如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。
关键词:
-
天天实时:ios app真机测试到上架App Store详细教程-必看
>转载:https: blog csdn net p312011150 article details 89374401iosapp真机测试到上架AppStore详细教
来源: 记录-对象有哪些继承方式_信息
天天实时:ios app真机测试到上架App Store详细教程-必看
ubuntu编译kernel
三、词法分析
焦点速讯:五一期间 市公交公司安全运送乘客48万余人次
微信2023五一大数据来了!十大景区花钱榜公布 你花了多少钱? 观焦点
《流浪地球》剧情成真!科学家首次观测到一颗行星被恒星吞噬 世界热门
每日观点:今年还有调休假:中秋国庆假期后要连上7天班!
全球新消息丨最新研究:外星人或利用手机信号绘制出地球地图
震撼!恒星吞噬行星全过程首次曝光 地球:我命休矣?
博客开通
【解决方法】解决锐捷EVE模拟器无法弹出选择CRT接管命令行和命令行 天天简讯
用例管理工具 禅道-当前速看
Web前端已死?别带节奏了,说白了就是“卷”
林志玲出席活动被问二胎做出回应称自己不会要二胎,一个就满足了
财政部:2023年中央财政继续支持实施并启动新的农村综合性改革试点试验
世界快看:电动车降价彻底无望?今日电池级碳酸锂涨价5000元/吨
骁龙8+待机47.9天如何实现?小米平板6系列“深度休眠”官方揭秘
【世界新视野】多样性算力推委会正式成立,透露哪些重要信号?
五一假期,江门水路发送旅客超15万人次 世界快报
TypeScript 学习笔记 — 模板字符串和类型体操(十五) 当前头条
天天日报丨(转载)性能测试应该怎么做?
在Zynq平台上使用uCOS [原创www.cnblogs.com/helesheng]-天天热文
ChatExcel?|焦点信息
全球讯息:【手记】翻新显卡安装驱动程序
信息:2022年跨境电商市场规模15.7万亿元
【新华500】新华500指数(989001)4日收涨0.05% 环球即时
新华社权威快报丨2023年“五一”假期全国营业性客运量合计26971.6万人次
【环球时快讯】6499元买吗?雷军晒小米13 Ultra限量定制色真机上手图:网友大呼背刺
家用强力灭蚊!雅格充电电蚊拍10.9元起狂促_报资讯
世界聚焦:“五一”假期日均125.3万人次出入境
报道:我设计了个【方案】:比redis好10倍的kv库【一统kv】
Apache Pulsar 在火山引擎 EMR 的集成与场景
PA 2022 部分题解_环球热门
ios app真机测试到上架App Store详细教程-必看 快播
奈雪五一小长假订单同比上涨120% 部分门店涨幅超800%|热资讯
【天天热闻】五一18人预付9600元订民宿遭毁约!青岛市监局立案调查
环球视讯!4月百城二手住宅价格跌幅扩大:挂牌量持续走高 房价走势承压
Hadoop运行集群搭建-世界速读
golang基础知识 环球快讯
聚焦:用手机号码归属地 API 开发的应用推荐
环球快资讯丨来了乌鲁木齐,相当于去了中东石油富豪区消费?
全面看齐新7系!宝马新一代5系G60外观、内饰首度公开亮相:发光双肾抢眼-全球速讯
门密码锁怎么加入指纹?第一次使用记住这4点 环球讯息
让Visual Studio用上chatgpt
【解决方法】白嫖利用WPS自带C盘清理大师,清理C盘空间,自测清理19.5G空间,太感人了! 当前快播
Linux安装部署Redis(超级详细)-全球看热讯
博安生物(6955.HK):地舒单抗注射液国际3期临床试验完成首例受试者入组|今日视点
纤薄身材也能满血发挥!耕升RTX 4070踏雪评测:2K游戏通吃的高颜值显卡 环球关注
购燃油车就送粤A蓝牌!广汽集团在广州推限时购车补贴
看不下去AI胡说八道 英伟达出手给大模型安了个“护栏”
世界通讯!鼠目寸光是什么生肖_鼠目寸光的意思及造句
世界微资讯!热门的常用 API 大全分享
观速讯丨Spring AOP官方文档学习笔记(三)之基于xml的Spring AOP
播报:常见未授权访问漏洞汇总
每日播报!AD主辅域控切换-辅域控制器升级为主域控制器-详细操作
Excel文件根据自定义模板生成标签或数据报表
2023山东东营市广饶县事业单位招聘面试通知书领取通知
u18包括18岁吗?足球比赛中的u系列是什么意思?
英雄联盟150位英雄名字是什么?2022lpl夏季赛赛程表
iphone手机看电子书能用什么格式?iphone电子书APP推荐
NBA 2K14存档文件在哪里?nba2k14电脑版键盘操作
十全食美多种零食 奥利奥大礼包39元1.6斤再发车
不涨价!小米13 Ultra限量定制色上架:16+512GB售价6499元
仙气飘飘 洛阳90后女生穿汉服开公交:展示传统文化之美
观察:发布整整10年后:第一代iPad Air被正式抛弃
刺客信条系列中哪个最好玩?刺客信条奥德赛选男还是女?
阿迪达斯官网买的产品是正品吗?阿迪达斯和耐克是什么关系?
承重墙允许开洞最大尺寸是多少?承重墙拆了要承担什么责任?
安陵容知道是宝鹃害她的吗?甄嬛传当年火到什么程度?
广交会里的“大食物观” 食品企业坚持科技创新|全球今日报
只种一颗杨梅树会结果吗?宏宝莱杨梅冰多少钱一袋?
怎么改蚂蚁庄园小鸡的名字?蚂蚁森林如何修改自己的昵称?
天天微速讯:学系统集成项目管理工程师(中项)系列17a_范围管理(上)
使用python查看五黄及罗猴
世界百事通!【访问者设计模式详解】C/Java/JS/Go/Python/TS不同语言实现
THE PLANETS MERCURY -环境变量的设置提权以及SETENV的理解
嵌入式测试手册——基于NXP iMX6ULL开发板(2)
gta4热咖啡补丁下载_GTA4热咖啡
京口法院微电影把诈骗“演”给你看|世界热门
五一假期返程现特种兵式学习:小学生高铁小桌板上疯狂赶作业
1盒不到3元!特仑苏全脂/低脂牛奶大促:高蛋白 易吸收
世界简讯:AMD正式发布锐龙7040U APU:最先进4nm Zen4、15W超低功耗
“非洲狮的好朋狗”?动物园回应圈养鸡羊狗:珍稀品种 非普通家禽|每日观点
320.37万人次,42.32亿元!海南“五一”旅游成绩单出炉 今日热文
观热点:第1章 大数据概述
世界热点评!内网穿透
工控机中部署Ubuntu 22.04 系统
【财经分析】贝泰妮高增长不再 股价跌去六成后能否再出发?
全球热点评!众智科技:4月28日获融资买入89.58万元,占当日流入资金比例19.76%
特斯拉中国突然涨价 销售催“等等党”赶紧下单:早买车就是赚到
路人如何衡量汽车品牌营销费用高低?李想支了一招:看留言-天天速讯
止渴解腻夏日必备!果舒拉桂花酸梅晶好价:3盒券后29.9
男子在西湖捞手机日入约一万!官方回应:不是景区工作人员
热火老将乐福本赛季中期从骑士买断加盟
襄阳市市场监管局开展“你点襄检”专项执法行动_全球头条
【国际大宗商品早报】经济衰退前景打压国际油价大幅下挫4% 美麦涨超5% 当前关注
中国影史第三!今年五一档电影总票房超15亿元
【天天播资讯】40系显卡3大优势!再买30系就冤了
世界热议:喂到嘴边的肥肉!新势力无奈破产:富士康喜提造车工厂一座