原型方法中的“this”在继承时未按预期解析

'this' inside prototype method not resolving as expected when inheritance

本文关键字:继承 方法 this 原型      更新时间:2023-09-26

我有一个构造函数,它是node.js中模块(https://github.com/fluxxu/evalidator)的扩展。此扩展构造函数在原型中定义了另外两个方法,并且 **方法 B 通过"this"关键字调用方法 A。此构造函数用于初始化另一个对象中的属性,当我从此属性调用方法 B 时,我收到一个错误,例如"main 对象"没有方法 A:

TypeError: Object function (){ superEvalidatorVar.method_B(); } 
has no method 'method_B' at Object.<anonymous> 

这是代码:

var EValidator = require('evalidator');

/**
 * EValidator extension object
 * @constructor
 */
function SuperEValidator(){
    // EValidator Inheritance
    EValidator.apply(this, arguments);
}
SuperEValidator.prototype = Object.create(EValidator.prototype);
SuperEValidator.prototype.constructor = SuperEValidator;
SuperEValidator.prototype.method_A = function(){
    console.log('method_A called');
};
SuperEValidator.prototype.method_B = function(){
    this.method_A();
};
var superEvalidatorVar = new SuperEValidator();
var mainObject = {
    callingSuperEValidator: function(){
        superEvalidatorVar.method_B();
    }
};
/*** Calling methods from MainObject ***/
mainObject.callingSuperEValidator.method_B(); // Throws Error!

**扩展构造函数method_B的"this"关键字解析为 mainObject,为什么?

  1. 在全局级别设置 var me; 并在 PropertyObject Constructor 中将其设置为 'this',然后在 method_B 内部使用 "me" 而不是 'this'。
  2. 在里面method_B使用"PropertyObject.prototype"而不是"this"

但我想知道是否发生了不好的事情,我不明白超级EValidator中的这种行为

编辑:

这一切的真正目的是重写猫鼬模式的"验证"方法:

PostSchema.methods.validate = function(cb){
    // 'this' will have the value of the object (model) from which the function will be called
    evPost.validate_super(this, cb);
};

问题不是由于thisthis完全是坚持EV。

问题是您首先使用 ev.__proto__==={} 创建 EV,然后重新分配SuperEValidator.prototype这会断开ev.__proto__的链接并SuperEvalidator.prototype

请注意,此处 SuperEValidator 的函数声明是提升的,而不是原型定义的函数声明。 因此,只需将主对象移动到底部即可解决问题。

var mainObject = {
    propertyObject: new PropertyObject(),
    ev: new SuperEValidator() // at the moment, ev.__proto__ === {}
};
...
// SuperEValidator.prototype has been assigned to another reference while ev.__proto__ is still {}
SuperEValidator.prototype = Object.create(EValidator.prototype);