Babel转译ES6类为ES5时优先使用Reflect.construct的原因是什么?
Reflect.construct 优先使用的核心原因
Super.apply(this, arguments) 只能覆盖老式ES5构造函数的继承场景,完全无法适配原生ES6类的继承逻辑,而Reflect.construct是为了完全对齐原生ES6类继承的标准行为设计的,具体必要性有三点:
- 避免原生类构造函数直接调用报错
原生ES6规范明确要求,class定义的构造函数只能通过new关键字调用,直接用apply/call执行原生类构造函数会直接抛出Class constructor cannot be invoked without 'new'的错误。如果运行环境支持Reflect,说明环境本身原生支持ES6类,此时如果用apply调用原生父类构造函数会直接执行失败,而Reflect.construct的作用就是模拟new调用的逻辑,不会触发报错。 - 正确传递
new.target取值
ES6类构造函数内部可以访问new.target变量,该变量指向实际被实例化的子类构造函数,很多高级特性(比如抽象类判断)都依赖这个值。Super.apply的调用方式完全无法传递new.target,会导致父类中依赖new.target的逻辑全部失效,而Reflect.construct的第三个参数就是用来指定new.target的取值,代码里_getPrototypeOf(this).constructor拿到的就是实际的子类构造函数,和原生new调用的new.target完全一致。 - 兼容内置类继承与特殊构造函数返回逻辑
继承Array、Date、Map等内置类,或者父类构造函数有显式返回对象的场景下,Super.apply(this, arguments)的方式无法正确初始化内置类的内部私有插槽,也无法正确处理父类返回对象的原型链绑定。Reflect.construct生成的实例会自动把原型指向第三个参数的prototype属性,完全对齐原生类继承的原型链规则,能完美覆盖这些特殊场景。
降级逻辑的合理性
如果环境不支持Reflect,说明环境本身就不支持原生ES6类,此时父类要么是Babel转译后的ES5构造函数,要么是老式的自定义构造函数,本身就支持apply/call调用,用Super.apply的降级方案可以正常运行。
内容的提问来源于stack exchange,提问作者Chor
相关产品推荐
相关产品推荐

