This question already has answers here:
What is the reason to use the 'new' keyword at Derived.prototype = new Base
                                
                                    (6个答案)
                                
                        
                                3年前关闭。
            
                    
我在网页中编写了事件HTML上下文的不同解析器。

基本结构如下:

注册事件并将其链接到解析器函数。

elem.addEventListener(
    'click',
    (e) => {
        let parser = new UiResultsItemInfoParser(e);
        eventInfo = parser.evntInfo;
        submitEvnt(eventInfo);
    }
);


UiResultsItemInforParser是称为EvntParser的超类型的子类型,而e显然是事件对象。

EvntParser看起来像这样:

function EvntParser (e) {
    this._evntInfo = {};
    this._evntInfo.time = e.timeStamp.toString();
    this._evntInfo.type = 'event';
}

EvntParser.prototype = {
    set evntInfo(e) {
        this._evntInfo.time = e.timeStamp.toString();
        this._evntInfo.type = 'event';
    },
    get evntInfo() {
        return JSON.stringify(this._evntInfo);
    }
};


UiResultsItemInforParser源自EvntParser,看起来像这样:

function UiResultsItemInfoParser(e) {
    EvntParser.call(this, e);
}

UiResultsItemInfoParser.prototype = new EvntParser();
UiResultsItemInfoParser.prototype.constructor = UiResultsItemInfoParser;


不幸的是,触发事件并在TypeError: e is undefined中创建一个新的this._evntInfo.time = e.timeStamp.toString();对象时,我在EvntParser中的UiResultsItemInfoParser行中得到了addEventListener

为什么会这样?如何在对象创建过程中以EvntParser访问事件对象的方式修复它?

最佳答案

这个

UiResultsItemInfoParser.prototype = new EvntParser();


是重复选择的反模式,也是问题的根源。 EvntParser需要一个参数并假定已为其提供参数(this._evntInfo.time = e.timeStamp.toString()),因此在执行上述操作时它会失败。

代替:

UiResultsItemInfoParser.prototype = Object.create(EvntParser.prototype);


这将创建一个以EvntParser.prototype为原型的对象,但不调用EvntParser。 (然后,您的下一行完全正确,将结果对象上的constructor修复。)

稍后,通过在子类构造函数中执行EvntParser.call(this, e);来执行正确的操作。所以这实际上只是一行。



由于您正在使用箭头功能,因此您必须在ES2015环境中工作。这意味着您可以使用新的class语法,该语法可以轻松完成所有工作:

class EvntParser {
    constructor(e) {
        this._evntInfo = {};
        this._evntInfo.time = e.timeStamp.toString();
        this._evntInfo.type = 'event';
    }
    set evntInfo(e) {
        this._evntInfo.time = e.timeStamp.toString();
        this._evntInfo.type = 'event';
    }
    get evntInfo() {
        return JSON.stringify(this._evntInfo);
    }
}

class UiResultsItemInfoParser extends EvntParser {
}


注意,您甚至不需要在UiResultsItemInfoParser中定义构造函数。当您不这样做时,JavaScript引擎会为您定义一个调用super及其所有收到的参数的引擎。



旁注:此:

this._evntInfo = {};
this._evntInfo.time = e.timeStamp.toString();
this._evntInfo.type = 'event';


也可以写

this._evntInfo = {
    time: e.timeStamp.toString(),
    type: 'event'
};


如果愿意(甚至在ES2015之前)。确实创建了相同的对象。

10-06 11:35