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

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

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

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

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

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
蓝屏代码0x00000b(0x0000000a蓝屏代码是什么意思?0x0000000a蓝屏代码解决方法汇总)