用过 React的读者知道,经常用 extends继承 React.Component:
React github源码:。
面试官可以顺着这个问 JS继承的相关问题js复制对象,比如: ES6的 class继承用ES5如何实现。据说很多人答得不好。
构造函数、原型对象和实例之间的关系
要弄懂extends继承之前,先来复习一下构造函数、原型对象和实例之间的关系。
代码表示:
笔者画了一张图表示:
ES6 extends 继承做了什么操作
我们先看看这段包含静态方法的 ES6继承代码:
其中这段代码里有两条原型链,不信看具体代码。
一图胜千言,笔者也画了一张图表示,如图所示:
结合代码和图可以知道, ES6extends 继承,主要就是:
1、把子类构造函数( Child)的原型( __proto__)指向了父类构造函数( Parent)。
2、把子类实例 child的原型对象( Child.prototype) 的原型( __proto__)指向了父类 parent的原型对象( Parent.prototype)。这两点也就是图中用不同颜色标记的两条线。
3、子类构造函数 Child继承了父类构造函数 Preant的里的属性。使用 super调用的( ES5则用 call或者 apply调用传参)。也就是图中用不同颜色标记的两条线。
看过《JavaScript高级程序设计-第3版》 章节 6.3继承的读者应该知道,这2和3小点,正是寄生组合式继承,书中例子没有第1小点。
1和2小点都是相对于设置了 __proto__链接。那问题来了,什么可以设置 __proto__链接呢。
设置proto
new、 Object.create和 Object.setPrototypeOf可以设置 __proto__。
说明一下, __proto__这种写法是浏览器厂商自己的实现。
再结合一下图和代码看一下的 new, new出来的实例的 __proto__指向构造函数的 prototype,这就是 new做的事情。
new 做了什么
1、创建了一个全新的对象。
2、这个对象会被执行 [[Prototype]](也就是 __proto__)链接。
3、生成的新对象会绑定到函数调用的 this。
4、通过 new创建的每个对象将最终被 [[Prototype]]链接到这个函数的 prototype对象上。
5、如果函数没有返回对象类型 Object(包含 Functoin, Array, Date, RegExg, Error),那么 new表达式中的函数调用会自动返回这个新的对象。
Object.create:ES5提供的
Object.create(proto,[propertiesObject]) 方法创建一个新对象,使用现有的对象来提供新创建的对象的 __proto__。
它接收两个参数,不过第二个可选参数是属性描述符(不常用js复制对象,默认是 undefined)。对于不支持 ES5的浏览器, MDN上提供了 ployfill方案:MDN Object.create()
Object.setPrototypeOf:ES6提供的
Object.setPrototypeOf() 方法设置一个指定的对象的原型(即内部 [[Prototype]]属性)到另一个对象或 null: Object.setPrototypeOf(obj,prototype)。
nodejs源码就是利用这个实现继承的工具函数的。
extends的ES5版本实现
知道了ES6 extends继承做了什么操作和设置 __proto__的知识点后,把上面 ES6例子的用 ES5就比较容易实现了,也就是说实现寄生组合式继承,简版代码就是:
我们完全可以把上述 ES6的例子通过 babeljs()转码成 ES5来查看,更严谨的实现。
如果对JS继承相关还是不太明白的读者,推荐阅读以下书籍的相关章节,可以自行找到相应的 pdf版本。
———END———
限 时 特 惠:本站每日持续更新海量各大内部创业教程,一年会员只需128元,全站资源免费下载点击查看详情
站 长 微 信:jiumai99