返回
js 实现继承的多种思路 + 原型链原理剖析
前端
2023-10-25 04:03:56
在js中,实现继承有多种途径,每种方式都有其独特的特点和适用场景,在本文中,我们将一一介绍这些方式,并对它们的优缺点进行比较,帮助开发者选择最适合自己项目和场景的继承方式。
### 1. 原型链
在js中,每个构造函数都有一个prototype对象,这个对象是所有实例的父对象。通过prototype对象,我们可以为构造函数的实例动态的添加属性和方法。由于这个特性,我们可以在一些框架实现中看到没有使用class去声明类而是使用构造函数,比如说Vue 2.x,这是因为构造函数的prototype具有更好的扩展性。
### 2. 构造函数
构造函数是js实现继承的传统方式,也是最简单的方式。通过使用new调用构造函数,我们可以创建一个新的实例。这个实例会继承构造函数的prototype对象的所有属性和方法。构造函数继承的缺点是,它不能继承构造函数本身的属性和方法,同时,如果一个类有多个父类,构造函数继承就会变得很复杂。
### 3. class
class是es6中引入的新语法,它提供了更加简洁的继承方式。class本质上还是使用构造函数来实现继承,但是它提供了更简洁的语法。在class中,我们可以使用extends关键字来指定父类,然后使用super关键字来调用父类的方法和属性。
### 4. 组合继承
组合继承是将构造函数和原型链继承结合起来的一种方式。这种方式继承了构造函数和原型链继承的优点,并且避免了它们的缺点。在组合继承中,我们首先使用构造函数来创建一个新的实例,然后将父类的prototype对象赋给这个实例的prototype对象。这样,这个实例就可以继承父类的所有属性和方法,同时还可以继承构造函数本身的属性和方法。
### 5. 寄生组合继承
寄生组合继承是组合继承的一种变体。这种方式与组合继承的区别在于,它使用了一个额外的函数来创建新的实例。这个函数会先创建一个新的空对象,然后将父类的prototype对象赋给这个空对象的prototype对象。最后,这个空对象会作为参数传递给构造函数,这样构造函数就可以在新的实例上添加自己的属性和方法。
### 6. 代理继承
代理继承是通过创建一个代理对象来实现继承的一种方式。代理对象会将目标对象的属性和方法代理到自己身上,这样,代理对象就可以继承目标对象的所有属性和方法。代理继承的缺点是,它不能继承构造函数本身的属性和方法。
### 7. 混入
混入是将多个对象的属性和方法合并成一个新对象的一种方式。混入可以用来实现多重继承,也可以用来将一些通用的属性和方法添加到多个对象中。混入的缺点是,它不能继承构造函数本身的属性和方法。
### 8. 鸭子类型
鸭子类型是一种不依赖于继承关系的继承方式。在鸭子类型中,只要一个对象拥有某个属性或方法,它就可以被当作拥有这个属性或方法的类的一个实例。鸭子类型的缺点是,它不能保证对象具有某个属性或方法,同时,它也不能保证对象的行为与某个类一致。
## 总结
js中实现继承的多种方式各有优缺点,开发者需要根据自己的项目和场景选择最适合的继承方式。一般来说,原型链继承和构造函数继承是使用最广泛的继承方式,而class继承和组合继承则是es6中引入的新方式,具有更简洁的语法和更强大的功能。代理继承和混入则是在某些特定场景下使用的一种继承方式。
## 进一步阅读
* [JavaScript继承(阮一峰)](https://www.ruanyifeng.com/blog/2011/06/inheritance_in_javascript.html)
* [深入理解js原型链](https://segmentfault.com/a/1190000021394508)
* [es6中class的继承](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Classes/extends)
* [组合继承与寄生组合继承](https://segmentfault.com/a/1190000019691204)
* [代理继承](https://segmentfault.com/a/1190000020437872)
* [混入](https://segmentfault.com/a/1190000020288855)
* [鸭子类型](https://segmentfault.com/a/1190000020323136)
## 参考资料
* [JavaScript 继承机制详解](https://www.cnblogs.com/zeaseyuan/p/7653269.html)
* [JavaScript继承的五种方式](https://www.jianshu.com/p/20e71a4d0d09)
* [es6中的class继承](https://segmentfault.com/a/1190000019591440)
* [组合继承与寄生组合继承](https://segmentfault.com/a/1190000019691204)
* [代理继承](https://segmentfault.com/a/1190000020437872)
* [混入](https://segmentfault.com/a/1190000020288855)
* [鸭子类型](https://segmentfault.com/a/1190000020323136)