首页IT科技js 原型原型链(记录–JS精粹,原型链继承和构造函数继承的 “毛病”)

js 原型原型链(记录–JS精粹,原型链继承和构造函数继承的 “毛病”)

时间2025-06-21 01:11:16分类IT科技浏览4789
导读:这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助...

这里给大家分享我在网上总结出来的一些知识            ,希望对大家有所帮助

我们来看看原型链继承的代码实现:

function SuperType() { this.property = true; } function SubType() { this.subproperty = false; } SuperType.prototype.getSuperValue = function() { return this.property; }; SubType.prototype.getSubValue = function () { return this.subproperty; }; SubType.prototype = new SuperType(); // 对 SubType 得原型链重新指定                     ,是原型链继承 let instance = new SubType(); console.log(instance.getSuperValue()); // true

还需要再额外说明查找关系吗??不懂得工友可见这篇 《歪理解?原型链中的函数和对象》

这里还是用代码展示下它们的指向关系吧:

上面例子中有 1 个对象 instance        , 两个函数         ,SuperType 和 SubType             。函数是上帝                    ,对象是基本物质                     。继承来自两方面:1. 继承自祖先(遗产);2. 继承自上帝(天赋);

// 继承自祖先(遗产) instance.__proto__ === SubType.prototype // true SubType.prototype.__proto__ === SuperType.prototype // true // 继承自上帝(天赋) SuperType.__proto__ === Function.prototype // true SubType.__proto__ === Function.prototype // true SuperType.prototype.__proto__ === Object.prototype // true Object.prototype.__proto__ === null // true

当然            ,我们并不是来讲原型链的        。重点是:点出原型链继承的“问题            ”!!

它的主要问题出现在:原型中包含引用值的时候      ,原型中包含的引用值会在所有实例间共享         。

function SuperType() { this.colors = ["red", "blue", "green"]; } function SubType() {} SubType.prototype = new SuperType() // 原型链继承 let s1 = new SubType() let s2 = new SubType() s1.colors.push("yellow") console.log(s1.colors) // [red, blue, green, yellow] console.log(s2.colors) // [red, blue, green, yellow]

colors 是个数组                   ,引用值                ,当它共享给 SubType 的时候   ,用的是引用值                  ,当我们实例化的时候                   ,如果其中一个实力对它做出了修改,将会影响到其它实例的引用                    。

其实               ,我们也知道                      ,很少在业务代码中这样去写继承:SubType.prototype = new SuperType()    ,原型链继承会造成复用的混乱            ,所以它基本不会被单独使用            。

构造函数继承

构造函数继承                     ,也叫做:“盗用构造函数                     ”        ,“对象伪装        ”或“经典继承         ”      。

基本思路:在子类构造函数中用 apply()和 call()方法调用父类构造函数                   。

上一小节的例子改造为:

function SuperType() { this.colors = ["red", "blue", "green"]; } function SubType() { SuperType.call(this) // 构造函数继承 } let s1 = new SubType() let s2 = new SubType() s1.colors.push("yellow") console.log(s1.colors) // [red, blue, green, yellow] console.log(s2.colors) // [red, blue, green]

完美解决原型链继承的问题         ,但是它也有它的问题                    ,也是使用构造函数模式自定义类型的问题            ,

即:必须在构造函数中定义方法(在原型上定义方法      ,子类是访问不到的)                   ,函数不能重用                。

function SuperType() { } function SubType() { SuperType.call(this) // 构造函数继承 } SuperType.prototype.fn = ()=>{} let s1 = new SubType() console.log(s1.fn) // undefined
function SuperType() { this.fn=()=>{} } function SubType() { SuperType.call(this) // 构造函数继承 } let s1 = new SubType() let s2 = new SubType() console.log(s1.fn === s2.fn) // false

而这一点                ,在原型链继承中   ,又是可以的   。                  。                   。

function SuperType() {} function SubType() {} SuperType.prototype.fn = ()=>{} SubType.prototype = new SuperType() // 原型链继承 let s1 = new SubType() console.log(s1.fn) // ()=>{}
function SuperType() { this.fn=()=>{} } function SubType() {} SubType.prototype = new SuperType() // 原型链继承 let s1 = new SubType() let s2 = new SubType() console.log(s1.fn === s2.fn) // true

所以                  ,综上                   ,原型链继承和构造函数继承的 “毛病                    ” 分别是:

原型链继承:所有继承的属性和方法都会在对象实例间共享,无法做到实例私有。 构造函数继承:子类不能访问父类原型上的方法               。

咱就是说               ,这东西怎么这么拧巴呢                      。    。            。

于是乎一个规避二者“毛病            ”的继承方式出现了:组合继承~~

组合继承

目前最流行的继承模式是组合继承!

思路是:使用原型链继承原型上的属性和方法                      ,而通过构造函数继承实例属性                     。

function SuperType(name){ this.name = name; this.colors = ["red", "blue", "green"]; } function SubType(name, age){ SuperType.call(this, name) // 构造函数继承 this.age = age; } SuperType.prototype.sayName = function() { console.log(this.name); } SubType.prototype = new SuperType() // 原型链继承 SubType.prototype.sayAge = function() { console.log(this.age); } let s1 = new SubType("Nicholas", 29) let s2= new SubType("Greg", 27) s1.colors.push("yellow") console.log(s1.colors) // [red, blue, green, yellow] console.log(s2.colors) // [red, blue, green] s1.sayName() // Nicholas s2.sayName() // Greg s1.sayAge() // 29 s2.sayAge() // 27

组合继承    ,总结起来就是            ,属性(特别是引用值)通过构造函数去继承                     ,而公用的            、需要复用的方法用原型链去继承!!

说实话        ,JS 继承真的很奇怪        。         。                    。并不是面向对象语言         ,又要通过原型链去模拟面向对象                    ,真的很多小坑的点需要去注意            。(哈哈哈            ,想想还是函数式好      ,清晰)

本文转载于:

https://juejin.cn/post/7107779239281164301

如果对您有所帮助                   ,欢迎您点个关注                ,我会定时更新技术文档   ,大家一起讨论学习                  ,一起进步      。

声明:本站所有文章                   ,如无特殊说明或标注,均为本站原创发布                   。任何个人或组织               ,在未征得本站同意时                      ,禁止复制                     、盗用        、采集         、发布本站内容到任何网站                    、书籍等各类媒体平台                。如若本站内容侵犯了原著者的合法权益    ,可联系我们进行处理   。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
分布式事务型数据库性能专项评测(多数据源事务处理-涉及分布式事务)