JavaScript的常用继承方式之原型链继承

观前提醒,阅读本文需要您掌握原型和原型链的概念,若没有这些前置知识,理解继承将相当困难

通过原型链实现继承

先看代码↓


//父类构造函数;
//tips:构造函数首字母一般大写,用来与普通函数作区分;
function Human(){
    this.friends = ['booker','cris'];
}
//在父类的原型链上定义可复用的方法;
Human.prototype.getFriends = function(){
    console.log(this.firends);
}
//子类构造函数
function Boy(name){
    this.name = name;
}
//将父类的实例赋值给子类构造函数的原型对象;
Boy.prototype = new Human();
//注意:对子类原型对象的修改必须在上一句代码之后!
Boy.prototype.getName = function(){
    console.log(this.name);
}

//这样是无效的,因为子类的原型对象的指向已经被修改了,所以先前对子类原型对象的赋值操作无法生效;
//Boy.prototype = new Human();
let boy = new Boy('jack');
console.log(boy);

再来看看控制台的打印结果

结论:

通过上面的图片,我们可以看到Boy类型的实例boy上不但拥有自己的属性(name),还拥有了Human类型的属性(即friends),这就说明了Boy与Human建立了某种联系,这种联系就是我们所说的继承,并且这种方式是通过原型链实现的.

原理:

修改子类原型对象的指向,核心代码:

Boy.prototype = new Human();

通过原型链实现继承存在的问题

通过原型链实现继承的主要弊端在于,如果父类属性中包含了引用类型的属性,如Object、Array等,那么子类所有的实例都会共享同一份属性,任何实例对该属性的修改都会反映到其他实例上,一般情况下这是我们所不想看到的情况,比如:

let boy1 = new Boy('jack');
let boy2 = new Boy('pual');
boy1.friends.push('Mary');
boy1.getFriends();//['booker','cris','Mary'];
boy2.getFriends();//['booker','cris','Mary'];

明明我们根本就没有对boy2做任何的操作,为什么boy2的friends属性也受到影响呢?

问题就出在了我们实现继承的方式上,回想一下这句代码:

Boy.prototype = new Human();

我们将一个Human的实例赋值给了Boy的原型对象,那么,请思考一下,一个Human的实例对象默认下是怎样的呢? 

 

一个Human实例正常情况下应该包含如下属性:

  1. 定义在构造函数内的所有属性(friends);
  2. 指向其原型对象的__proto__;

那么Boy的原型对象也应该具有这些属性,并且你会发现,父类构造函数中的属性(friends)被绑定到了子类的原型对象上了(非常重要)

这个时候,当我们实例化一个Boy类型的对象时,会发生什么?

let boy = new Boy('jack');//会发生什么?
  1. 首先,Boy的构造函数会被调用,并把'jack'作为参数传递给构造函数,最终将对象返回给boy变量;
  2. JavaScript内部会自动将构造函数Boy的原型对象(__proto__)绑定到实例boy上;

还记得我们刚刚说到的      "父类构造函数中的属性(friends)被绑定到了子类的原型对象上了"   这句话吗?

这就是问题所在了,我们知道,定义在原型对象上的属性是被所有实例对象所共享的,所以,boy1和boy2的friends属性看似是相互独立,互不相干的变量,但实际上他们都指向了同一个内存地址,这就是通过原型链方式实现继承的最大弊端。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值