eventemitter3创建的对象constructor属性为undefined的问题咨询
为什么eventemitter3实例的
constructor属性是undefined? 这个问题其实是eventemitter3的设计特性导致的,我来给你拆解清楚:
首先,MDN那句“所有对象都具备constructor属性”其实有个容易被忽略的前提——这里的对象指的是默认继承自Object.prototype的普通对象。而eventemitter3为了性能优化,特意修改了它的原型链结构:
eventemitter3的作者将EventEmitter.prototype的原型设置成了null(而不是默认的Object.prototype),并且没有在这个原型对象上显式定义constructor属性。这样一来,当你创建一个事件发射器实例(比如你的temp1)时,它的原型链是:temp1 → EventEmitter.prototype → null
而普通JS对象的原型链是:普通对象 → Object.prototype → null
因为EventEmitter.prototype本身没有constructor属性,也没法从上层的null继承到,所以当你访问temp1.constructor时,自然就返回undefined了。
验证结论的小技巧
你可以在控制台里跑这几行代码确认:
const EventEmitter = require('eventemitter3'); const temp1 = new EventEmitter(); // 查看temp1的原型对象 console.log(Object.getPrototypeOf(temp1)); // 检查这个原型对象自身有没有constructor属性 console.log(Object.hasOwnProperty.call(Object.getPrototypeOf(temp1), 'constructor')); // 会返回false // 查看原型对象的原型是不是null console.log(Object.getPrototypeOf(Object.getPrototypeOf(temp1))); // 会返回null
怎么获取构造函数?
如果你确实需要拿到实例的构造函数,有两种简单的方式:
- 直接使用
EventEmitter本身(毕竟你就是用它创建的实例) - 手动给
EventEmitter.prototype添加constructor属性:
EventEmitter.prototype.constructor = EventEmitter; // 之后再访问temp1.constructor就会得到EventEmitter了
补充一下为什么eventemitter3要这么做
这么设计主要是为了性能:当遍历_events对象里的事件时,不用额外做hasOwnProperty检查(因为_events也是用Object.create(null)创建的,没有原型链属性),同时原型链更短,属性查找更快。
内容的提问来源于stack exchange,提问作者River Tam
相关产品推荐
相关产品推荐

