资讯专栏INFORMATION COLUMN

高程3版中《寄生组合式继承》中的一个错误

lufficc / 1477人阅读

摘要:例如假如定义第二个子类然后在第一个子类中重新定义方法最后的输出结果是由此可以看出,中的方法也发生了改变,如果将替换成方法,就不会存在这样的问题。

前言

最近一直在回顾js继承方式,在阅读《高级程序设计》第3版 的时候遇到一个问题,下面仅个人看法,如果有理解错误或者不同看法,欢迎一起探讨:

正文

何谓寄生组合继承,实质上分为两步:

将父类的原型对象赋值给子类的原型对象

将子类原型对象中的constructor指针指向子类构造函数

这样就实现了继承,具体代码如下所示(书中原代码):

function SuperType(name){
    this.name = name;
}

SuperType.prototype.sayName = function(){
    console.log(this.name);
}

function SubType(name, age){
    SuperType.call(this, name);
    this.age = age;
}

function inheritPrototype(subType, superType){
    const subPrototype =  Object(superType.prototype);
    subPrototype.constructor = SubType;
    subType.prototype = subPrototype;
}

inheritPrototype(SubType, SuperType);

SubType.prototype.sayAge = function(){
    console.log(this.age);
}

const sub_1 = new SubType("liumin", "23");

sub_1.sayName();
sub_1.sayAge();

在inheritPrototype函数当中正是完成了上面的两个步骤,但是注意这里是通过Object函数创建一个对象赋值给subPrototype的,接下来我们了解一下Object函数

Object函数

为给定值创建一个对象包装器,如果传入的是undefined 或者 null,则返回一个空对象;否则返回一个给定值对应类型的对象;

    console.log(Object(undefined));
    console.log(Object(null));
    console.log(Object("123"));
    console.log(Object(123));

输出结果是:

如果传入的参数是一个对象,那么通过Object返回的则是对这个对象的引用,如下所示:

const person = {
    name:"xiaohong",
    age:"23",
    grade:"12",
}

const anotherPerson = Object(person);
console.log(anotherPerson === person);

输出结果:

person和anotherPerson引用的是同一块内存地址,这与Object.create(obj)是有差别的,Object.create(obj)是在内存中新开辟一个空间

存在的问题

如果在上述的继承方式中存在一个问题,如果之后通过子类的原型对象对父类中的sayName方法进行重新定义,这时候就会修改父类中的sayName方法,从而继承父类的其他子类中的sayName方法也就会被篡改掉,造成混乱。
例如:
假如定义第二个子类——SubTypeCopy:

function SubTypeCopy(name, height){
    SuperType.call(this, name);
    this.height = height;
}
inheritPrototype(SubTypeCopy, SuperType);

然后在第一个子类中重新定义sayName方法:

SubType.prototype.sayName = function(){
  console.log(`my name is:${this.name}`);
 }

const sub_1 = new SubType("liumin", "23");
const sub_2 = new SubTypeCopy("liujie","180");

sub_1.sayName();
sub_2.sayName();

最后的输出结果是:

由此可以看出,SubTypeCopy中的sayName方法也发生了改变,如果将Object替换成Object.create(obj)方法,就不会存在这样的问题。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/94824.html

相关文章

  • JS高程笔记 - 继承

    摘要:下面来看一个例子继承属性继承方法在这个例子中构造函数定义了两个属性和。组合继承最大的问题就是无论什么情况下都会调用两次超类型构造函数一次是在创建子类型原型的时候另一次是在子类型构造函数内部。 组合继承 组合继承(combination inheritance),有时候也叫做伪经典继承,指的是将原型链和借用构造函数的技术组合到一块,从而发挥二者之长的一种继承模式。其背后的思路是使用原型链...

    fsmStudy 评论0 收藏0
  • JavaScript高程第六章:继承-理解与实践

    摘要:高程第六章继承理解与实践昨日细细的读了一遍高程现在写篇文章来巩固下认知吧读首先是从中读到了什么我自己也在读书的时候用笔记下了各个部分的点现在等于阅读笔记回忆下书本理解基础第五版中规定了两种属性数据属性访问器属性数据属性包含一个数据值的位 JavaScript高程第六章:继承-理解与实践昨日细细的读了一遍JavaScript高程,现在写篇文章来巩固下认知吧. 读 首先是从中读到了什么,我...

    mozillazg 评论0 收藏0
  • JS高程读书笔记--第六章原型继承

    摘要:高程读书笔记第六章理解对象创建自定义对象的方式有创建一个实例,然后为它添加属性和方法。创建了自定义的构造函数之后,其原型对象默认只会取得属性至于其他方法都是从继承而来的。 JS高程读书笔记--第六章 理解对象 创建自定义对象的方式有创建一个Object实例,然后为它添加属性和方法。还可用创建对象字面量的方式 属性类型 ECMAScript在定义只有内部采用的特性时,描述了属性的各种特征...

    EasonTyler 评论0 收藏0
  • 面向对象的小九九

    摘要:由构造函数返回的对象就是表达式的结果。如果构造函数没有显式返回一个对象,则使用步骤创建的对象。运算符返回一个布尔值,表示对象是否为某个构造函数的实例。 面向对象 本人能力有限,有误请斧正 本文旨在复习面向对象(不包含es6) 本文学习思维 创建对象的方式,获取对象属性 构造函数,构造函数的new 做了什么 原型与原型对象 原型链 继承(借用构造继承、原型继承、组合继承、寄生组合继承)...

    时飞 评论0 收藏0
  • 高程(第六章) 面向对象的程序设计

    摘要:对于采用这种模式的对象,还可以使用操作符确定它的类型寄生构造函数模式通常,在前述的几种模式都不适用的情况下,可以使用寄生构造函数模式。这个模式可以在特殊的情况下用来为对象创建构造函数。 ECMA-262把对象定义为:无序属性的集合,其属性可以包含基本值、对象或者函数。严格来讲,这就相当于说对象是一组没有特定顺序的值。 1 理解对象 创建对象: var person = new Obje...

    ranwu 评论0 收藏0

发表评论

0条评论

lufficc

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<