你知道JavaScript的继承有几种写法吗?

标题的灵感来源于鲁迅的小说《孔乙己》中孔乙己和小伙计的一段对话:“茴香豆的茴字,怎样写的?......回字有四样写法,你知道么?”

这里我们并不探讨封建制度下穷苦潦倒的读书人的迂腐,回字的几种写法留给汉语言的同学去研究吧,今天我们讨论JavaScript继承的几种写法,由浅入深,一层层剥开她的面纱,最后给出一个最佳实践。

一、通过构造函数实现继承

function Parent() {
  this.name = 'name';
}
Parent.prototype.say = function () {
  console.log('say');
}
function Child() {
  Parent.call(this);
  this.type = 'child';
}
const child = new Child();

这种方式通过在子类的构造函数中调用父构造函数实现继承,但是有个致命的缺点:如下图,子类实例并不能继承父类中原型对象上的属性或者方法。 

二、通过原型对象实现继承

function Parent() {
  this.name = 'name';
  this.favor = ['blue', 'red'];
}
Parent.prototype.say = function () {
  console.log('say');
}
function Child() {
  this.type = 'child';
}
Child.prototype = new Parent();
const child = new Child();

这种方式通过给子类构造函数的prototype对象赋值实现继承,如下图,无论是name属性还是say方法都能被子类实例访问到。

但是这种方式也有缺点,如下图,当父类的属性是引用类型时,子类实例继承的是同一份属性,任一实例改变该属性都会引起全局变化,无法互相隔离。

三、组合方式

function Parent() {
  this.name = 'name';
  this.favor = ['blue', 'red'];
}
Parent.prototype.say = function () {
  console.log('say');
}
function Child() {
  Parent.call(this);
  this.type = 'child';
}
Child.prototype = new Parent();
const child = new Child();

 结合了上两种方式,避免了上面的缺点。但是这种方式在每次实例化子类实例时,都会调用两次父类构造函数,需要优化。

四、组合优化①

function Parent() {
  this.name = 'name';
  this.favor = ['blue', 'red'];
}
Parent.prototype.say = function () {
  console.log('say');
}
function Child() {
  Parent.call(this);
  this.type = 'child';
}
Child.prototype = Parent.prototype;
const child = new Child();

在给子类prototype赋值时不要采用实例化父类的方式,直接赋值父类的prototype。

其实,这种方式也有缺点:如下图,子类实例的constructor属性直接指向了父类构造函数,导致无法判断当前对象实例化自哪个构造函数。

五、组合优化②

function Parent() {
  this.name = 'name';
  this.favor = ['blue', 'red'];
}
Parent.prototype.say = function () {
  console.log('say');
}
function Child() {
  Parent.call(this);
  this.type = 'child';
}
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
const child = new Child();

终极改造完成:通过Object.create()方法指定了子类实例的__proto__属性,同时显式声明子类的constructor。

 

—本文完—

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值