extendsReact.Component
ES6classES5
构造函数、原型对象和实例之间的关系要弄懂extends继承之前,先来复习一下构造函数、原型对象和实例之间的关系。
代码表示:
笔者画了一张图表示:
构造函数
ES6 extends 继承做了什么操作ES6
其中这段代码里有两条原型链,不信看具体代码。
一图胜千言,笔者也画了一张图表示,如图所示:
构造函数(Parent)
结合代码和图可以知道, ES6extends 继承,主要就是:
- 把子类构造函数( Child)的原型( proto)指向了父类构造函数( Parent)。
- 把子类实例 child的原型对象( Child.prototype) 的原型( proto)指向了父类 parent的原型对象( Parent.prototype)。这两点也就是图中用不同颜色标记的两条线。
- 子类构造函数 Child继承了父类构造函数 Preant的里的属性。使用 super调用的( ES5则用 call或者 apply调用传参)。也就是图中用不同颜色标记的两条线。
看过《JavaScript高级程序设计-第3版》 章节 6.3继承的读者应该知道,这2和3小点,正是寄生组合式继承,书中例子没有第1小点。
1和2小点都是相对于设置了 proto链接。那问题来了,什么可以设置 proto链接呢。
设置 protonewObject.createObject.setPrototypeOf__proto__
__proto__
__proto__new
new 做了什么- 创建了一个全新的对象。
- 这个对象会被执行 [[Prototype]](也就是 proto)链接。
- 生成的新对象会绑定到函数调用的 this。
- 通过 new创建的每个对象将最终被 [[Prototype]]链接到这个函数的 prototype对象上。
- 如果函数没有返回对象类型 Object(包含 Functoin, Array, Date, RegExg, Error),那么 new表达式中的函数调用会自动返回这个新的对象。
Object.create(proto,[propertiesObject])__proto__
undefinedMDN Object.create()
Object.setPrototypeOf:ES6提供的Object.setPrototypeOf()Object.setPrototypeOf(obj,prototype)
nodejs
extends的ES5版本实现ES6 extends__proto__
我们完全可以把上述 ES6的例子通过 babeljs转码成 ES5来查看,更严谨的实现。
如果对JS继承相关还是不太明白的读者,推荐阅读以下书籍的相关章节,可以自行找到相应的 pdf版本。
推荐阅读JS继承相关的书籍章节《JavaScript高级程序设计第3版》第6章——面向对象的程序设计
6种继承的方案,分别是原型链继承、借用构造函数继承、组合继承、原型式继承、寄生式继承、寄生组合式继承。图灵社区本书地址,后文放出 github链接,里面包含这几种继承的代码 demo。
《JavaScript面向对象编程第2版》第6章——继承
12种继承的方案:
- 原型链法(仿传统)
- 仅从原型继承法
- 临时构造器法
- 原型属性拷贝法
- 全属性拷贝法(即浅拷贝法)
- 深拷贝法
- 原型继承法
- 扩展与增强模式
- 多重继承法
- 寄生继承法
- 构造器借用法
- 构造器借用与属性拷贝法
《ES6标准入门》第21章——class的继承
《深入理解ES6》第9章——JavaScript中的类
《你不知道的JavaScript》上卷第6章——行为委托和附录A(ES6中的class)
总结继承对于JS来说就是父类拥有的方法和属性、静态方法等,子类也要拥有。子类中可以利用原型链查找,也可以在子类调用父类,或者从父类拷贝一份到子类等方案。
继承方法可以有很多,重点在于必须理解并熟。
悉这些对象、原型以及构造器的工作方式,剩下的就简单了。寄生组合式继承是开发者使用比较多的。
回顾寄生组合式继承,主要就是三点:
- 子类构造函数的 proto指向父类构造器,继承父类的静态方法
- 子类构造函数的 prototype的 proto指向父类构造器的 prototype,继承父类的方法。
- 子类构造器里调用父类构造器,继承父类的属性。