Blog
Blog copied to clipboard
原型与原型链 - 实现继承的方式及优缺点
实现继承的方式及优缺点
面向对象编程
面向对象编程(Object Oriented Programming),简称OOP,是一种程序设计思想。OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。
面向对象编程的三大基本特性:封装,继承,多态。
封装
将一段逻辑/概念抽象出来做到“相对独立”。封装的概念并不是OOP独有的,而是长久以来一直被广泛采用的方法。主要目的总结为两点:
- 封装数据和实现细节。达到保护私有内容、使用者无需关心内部实现、且内部变化对使用者透明的目的。
- 封装变化。将不变和可变部分隔离,提升程序稳定性、复用性和可扩展性。
JavaScript中典型的封装就是模块化,实现方法有闭包、ES Module、AMD、CMD、CommonJS等。
多态
多态的概念也不是OOP独有的。所谓多态就是同一操作作用于不同的对象上面,可以产生不同的解释和不同的执行结果。
多态的目的就是用对象的多态性消除条件分支语句,提升程序的可拓展性。
JavaScript是一门弱类型多态语言,具有与生俱来的多态性。
继承
两大概念:
- 类(Class):抽象的模板;
- 实例(Instance):根据类创建的具体对象。
JavaScript中没有类的概念,使用构造函数作为对象模板,通过原型链来实现继承(ES6 中的Class
只是语法糖)。
原型及原型链相关知识详见深入JavaScript系列(六):原型与原型链
类式继承
将父类实例赋值给子类原型。缺点如下:
- 父类实例过早创建,无法接受子类的动态参数;
- 子类所有实例原型为同一父类实例,修改父类实例属性会影响所有子类实例。
function SupClass() {...}
function SubClass() {...}
SubClass.prototype = new SupClass()
构造函数式继承
子类构造函数中执行父类构造函数。缺点如下:
- 无法继承父类原型上的属性和方法。
function SupClass() {...}
function SubClass() {
SupClass.call(this, arguments)
}
组合式继承
类式继承+构造函数继承。缺点如下:
- 父类构造函数需调用两次。
function SupClass() {...}
function SubClass() {
SupClass.call(this, arguments)
}
SubClass.prototype = new SupClass()
原型式继承
对类式继承的封装,功能类似Object.create
,缺点如下:
- 若每次传入同一个原型,还是存在修改后影响其他子类实例的问题。
function createObj(o) {
function F() {}
F.prototype = o
return new F()
}
寄生式继承
拓展原型式继承
创建的对象并返回。
function createObj(o) {
const obj = Object.create(o)
obj.name = 'Logan'
return obj
}
寄生组合式继承
寄生式继承+构造函数式继承。
function inherit(child, parent) {
const p = Object.create(parent.prototype)
child.prototype = p
p.constructor = child
return child
}
function SupClass() {...}
function SubClass() {
SupClass.call(this)
}
SubClass = inherit(SubClass, SupClass)