为什么Mongoose Model构造函数的原型不是Function.prototype?
问题底层原理解释
你之前的认知没有错,普通构造函数的[[Prototype]](即Object.getPrototypeOf()取到的值)确实是Function.prototype,但Mongoose的模型类符合ES6类继承的特殊规则,不属于普通构造函数的场景。
核心规则:ES6类继承会设置两条独立的原型链
当使用class 子类 extends 父类语法实现继承时,JS引擎会同时处理两条原型链:
- 供实例使用的原型链:
子类.prototype.__proto__ === 父类.prototype,用来继承父类定义的实例方法 - 供构造函数本身使用的原型链:
子类.__proto__ === 父类,用来继承父类定义的静态方法、静态属性
我们可以用极简代码验证这个规则:
class Parent {} class Child extends Parent {} // 构造函数本身的原型指向父类 console.log(Object.getPrototypeOf(Child) === Parent); // true // 父类的原型才指向Function.prototype console.log(Object.getPrototypeOf(Parent) === Function.prototype); // true // 完全可以正常用new调用子类构造函数 const child = new Child();
对应到Mongoose的逻辑
conn.model()的内部逻辑,就是动态生成一个继承了mongoose.Model的子类:
- 动态创建的
MyModel就是上面例子里的Child,mongoose.Model就是Parent - 所以
Object.getPrototypeOf(MyModel) === mongoose.Model完全符合JS规范 - 这条原型链的作用是让你可以直接在
MyModel上调用mongoose.Model定义的静态方法,比如MyModel.find()、MyModel.create()等常用的模型方法 - 它的原型链完整路径是
MyModel -> mongoose.Model -> Function.prototype -> Object.prototype,完全满足构造函数的要求,所以可以正常用new MyModel()创建文档实例。
你之前的认知偏差是只记住了普通构造函数的原型指向,忽略了类继承场景下构造函数本身的原型会指向父类构造函数的规则。
内容的提问来源于stack exchange,提问作者user2897377
相关产品推荐
相关产品推荐

