JavaScript 是一种类型松散的语言,它支持多路触发,异步事件驱动等,并最好用于前端开发。为了使 JavaScript 拥有更加完整、更加完备的语言功能,ECMAScript 规范里面不断地增加新特性。其中,继承方式也是为数不多的,但它却是非常重要的,本文将来介绍 ES6 和 ES7 中支持的 JavaScript 继承方式并剖析其原理。
继承方式
1. 原型链继承
原型式继承相对来说比较简单,就是让一个对象继承另外一个对象的属性和方法,从而使它们成为一类。我们使用新的方式建立一个对象。
-- -------------------- ---- ------- -------- -------- - --------- - --------- - ---------------------- - -------- -- - ---------------- - - ----------- -- -------- ------- -- --------------- - --- --------- ----- ----- - --- -------- --------------------------- -- --- ---------
Child 的实例 new 子类的时候,就可以通过__proto__将 Child 的属性和方法链接到其原型对象上,也就实现了对 Parent 的属性和方法继承。
但缺点也很明显,就是共享父类属性,在许多实例需要改变父类的属性,我们就需要单独设置,而且当创建子类实例的时候不能直接往父类构造函数传递参数。
2. 借助构造函数继承
使用 call 或 apply 的方式,把父类的对象数据复制给子类对象。这样就设计到一个问题,就是无法继承父类的方法,子类只能继承这些方法的拷贝。
-- -------------------- ---- ------- -------- ------------ - --------- - ----- - -------- ----------- - ----------------- ------ ---------------------------------------- - ----- ----- - --- -------------- ------------------------ -- ----
知道原理就不难发现这种方式有巨大的局限性,当然也可以通过 Child.prototype = new Parent() 的方式来解决继承问题,不过这样也会带来同样的问题:子类实例将会共享 Parent 的属性和方法。
3. 组合继承(伪经典继承)
原型链方法继承父类的属性和方法(并解决了共有属性和方法的问题),借用构造函数来实现继承父类对象的属性。
-- -------------------- ---- ------- -------- ------------ - --------- - ----- - ---------------------- - -------- -- - ---------------- - - ----------- -- -------- ----------- ---- - ----------------- ------ -------- - ---- - --------------- - --- --------- --------------------------- - ------ ----- ----- - --- ------------- ---- --------------------------- -- --- ---- ----------------------- -- --
4. 原型式继承
原型式继承的方式其实是创建一个新的对象,然后利用 Object.create 创建一个原型,然后再通过 Object.create 方法进行增强、拷贝、继承一个新对象等操作。
虽然这个方式听上去也比较特别,但它的实质就是简化版的原型链继承,而且复制的属性、方法借助了 ES5 提供的 Object.create()。
-- -------------------- ---- ------- -------- -------- - --------- - --------- - ---------------------- - -------- -- - ---------------- - - ----------- -- ----- ----- - ------------------------------- ---- ---------- - -------- --------------------------- -- --- -----
5. ES6 类式继承
ES6 中的类式继承对 JavaScript 继承的原生语法进行了封装和简化,让继承更加接近传统面向对象中的语言。
可以使用 extends 关键字来实现继承,子类的构造函数中通过关键字 super 则可以调用父类的构造函数。
-- -------------------- ---- ------- ----- ------ - ----------------- - --------- - ----- - ------- - ---------------- - - ----------- - - ----- ----- ------- ------ - ----------------- ---- - ------------ -------- - ---- - - ----- ----- - --- ------------- ---- --------------------------- -- --- ---- ----------------------- -- --
6. ES7 中的 Object.setPrototypeOf 和 Object.assign 继承
ES7 引入的 Object.setPrototypeOf 方法和 Object.assign 方法来替换掉了原有的 Object.create 等等伪继承方法。
Object.setPrototypeOf 方法将一个指定的对象的原型设置成另一个对象或者是 null。并且,我们还需要在开头提示使用 ES2015+ 的语法。
-- -------------------- ---- ------- ----- ------ - - ------- - ---------------- - - ----------- - -- ----- ----- - - ---------- ------- ----- -------- ---- -- -- --------------------------- -- --- ----- ----------------------- -- --
Object.assign 方法虽然是比较常见的原型继承方式,但实际上它的本质并不是继承,它只能复制一个或多个源对象的自有属性到目标对象中。
-- -------------------- ---- ------- ----- ------ - - ----- --------- ------- - ---------------- - - ----------- - -- ----- ----- - --- -------------------- -------- --------------------------- -- ---------- ----------- -- --- - -------- ------------------------ -- ------
总结
继承是一种极为重要的语言特性,在 JS 基础上高效使用 OOP 的思想是值得学习的,掌握继承方式有助于你更好地使用 JavaScript 语言,提高自己的编程能力。在实际应用中,请酌情选择不同继承方式,每种方式各有利弊,看具体情况而定。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/6520b64195b1f8cacd825862