趣谈js的六种继承方式

本文详细解析了JavaScript中原型链继承、构造函数继承、组合式继承、原型式继承和寄生式继承的优缺点,以及寄生组合式继承的高效解决方案。通过实例对比,展示了如何实现多继承、访问父类原型数据和保持代码简洁的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

注:本文内容知识来源 https://www.cnblogs.com/ranyonsue/p/11201730.html

故事一

1. 原型链继承

子类构造函数.prototype = new 父类构造函数

缺点

  • 子类实例无法像父类构造函数传参。
  • 子类实例共享父类实例的属性,且父类原型上的属性是共用的。
  • 只能继承一个父类。

思考

子类实例:我能通过隐式原型__proto__拿到父类实例的属性,但是我俩是共用相同的属性哎!虽然他是我爸,但是…而且,别人java都允许有干爹(接口),为啥我没有?

我:得加钱…

于是,构造函数继承出现了。

2. 构造函数继承

function 子类构造函数() {
	// 设置子类属性
	this.属性 = ...
	// 执行父类构造函数
	父类构造函数1.call()
	父类构造函数2.call()
	// ...
}

优缺点

缺点:

  • 无法继承父类原型的属性,只继承了父类构造函数属性。
  • 臃肿,每个实例都拥有父类构造函数的副本

优点:可以继承多个父类。

思考

子类实例:通过一系列的call、apply,我终于有干爹了!但是,我亲爸还是我亲爸啊,为什么我亲爸的东西(无法通过原型链__proto__拿到父类原型上的数据)我不能用了呢?不行,我得跟我爸说去!

我:还得加钱…

于是,组合式继承出现了。

3. 组合式继承

function 子类构造函数() {
	// 添加子类属性
	this.属性 = 
	// 执行父类构造函数
	父类构造函数1.call()
	父类构造函数2.call()
	// ...
}

子类构造函数.prototype = new 父类构造函数

优缺点

缺点:重复调用了两次父类的构造函数

优点:

  • 允许继承多个类。
  • 可以拿到父类原型的数据。

思考

子类实例:完美!我不仅有很多干爸(call、apply),而且我还能和亲爸共享属性。

路人:看起来不错!但是,作为有洁癖的路人发现父类构造函数执行了有可能执行2次,浪费了内存。

我:不干了,跑路!
在这里插入图片描述

于是,故事一告1段落…

故事二

4. 原型式继承

function container(父类实例) {
	function 子类构造函数() {}
	子类构造函数.prototype = 父类实例
	return new 子类构造函数
}

// 使用
const 子类实例 = container(父类实例)

缺点

  • 不便复用(新实例的属性只能打点)
  • 继承单一

思考

子类实例:这这这,是我吗?我说他不是我(没有明确的子类函数),你说他就是我,我觉得这TM根本就不是我!

我:得加钱…

5. 寄生式继承

function container(父类实例) {
	function 子类构造函数() {}
	子类构造函数.prototype = 父类实例
	return new 子类构造函数()
}

function 真丶子类构造函数(父类实例) {
	const 子类实例 = container(父类实例)
	// 添加属性
	子类实例.属性 = ...

	return 子类实例
}

// 使用
const 子类实例1 = 真丶子类构造函数(父类实例)

优缺点

缺点:子类未用到原型,无法实现复用。

优点:有明确的子类函数,不需创建自定义类型。

思考

子类实例:爹啊~我终于找到你了(有明确的子类函数)!我还可以感受到爸爸对我的爱(子类实例可通过原型链访问到父类显式原型prototype的数据),但是妈妈的爱我感受不到啊!真丶子类构造函数未用到原型,无法复用相关数据)。

我:我的错我的错,马上改!

6. 寄生式组合继承

function container(父类实例) {
	function 子类构造函数() {}
	子类构造函数.prototype = 父类实例
	return new 子类构造函数()
}

// 组合
function Sub() {
	父类构造函数.apply()
}

Sub.prototype = container(父类实例)

// 使用
const 子类实例 = new Sub()

思考

子类实例们:真好,爸爸妈妈的爱都在哎,我们是幸福的一家人!

总结

此时,寄生组合式继承实现功能具体如下:

  1. 干爹 — call、apply,实现多继承。
  2. 爸爸妈妈的爱 — 子类实例可以访问到子类和父类构造函数的原型数据。
  3. 这就是我! — 有明确的子类函数。
  4. 消除洁癖 — 父类构造函数仅执行一次。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值