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

前言

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

正文

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

  1. 将父类的原型对象赋值给子类的原型对象
  2. 将子类原型对象中的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)方法,就不会存在这样的问题。

原文链接:segmentfault.com

上一篇:Sublime Text3 React开发常用插件
下一篇:详解REST架构风格

相关推荐

  • 这是使用终极版中删除项的正确方式呢?

    Felix KlingCarlo提出了一个问题:Is this the correct way to delete an item using redux?,或许与您遇到的问题类似。

    3 年前
  • 尝鲜vue3.0- 扶我起来学一下组合式API(5)

    背景 延续前面的三篇文章: 尝鲜vue3.0-从ToDoList开始(1) 尝鲜vue3.0-了解变化(2) 尝鲜vue3.0-tyepscript开发组件(3) 尝鲜vue3.0- ...

    2 个月前
  • 又一篇介绍vue3.0组合式api的文章

    开头 9月19号,万众期待的vue3.0如期而至,事实上很多人很早就已经体验过了,但是本人比较懒,再加上没有正式发布也不能在项目上使用,所以一直没去尝试,只在一些零星的文章上看到了它大概会有一些什么新...

    2 个月前
  • Vue 3 组合式 provide/inject

    组合式提供与注入 在之前的章节,我们讲了选项式的 提供与注入,今天我们继续讲组合式提供与注入。 我们也可以在组合式 API 中使用 provide/inject。两者都只能在当前活动实例的 setup...

    9 天前
  • JavaScript常用的继承--组合式继承

    组合继承有时候也叫伪经典继承,指的是将原型链和借用构造函数技术组合到一块,从而发挥二者之长的一种继承模式,其背后的思路是使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承。

    4 年前
  • JS面向对象的程序设计之继承的实现-寄生组合式继承

    组合继承是JavaScript最常用的继承模式。 不过,它也有自己的不足。 组合继承最大的问题就是无论在什么情况下,都会调用两次超类型构造函数: 一次是在创建子类型原型的时候。

    2 年前

官方社区

扫码加入 JavaScript 社区