如果子类中已覆盖原始基类方法,该如何访问?

时间:2019-05-21 06:50:33

标签: javascript mongodb

我通过用我自己的版本通过覆盖原始Javascript类和方法的扩展来扩展它们和方法,从而代替了它们。但是,有时我在覆盖的方法中想访问原始方法。但是,javascript只允许我执行某些操作,而其他时候则不允许。这是非常不可预测的行为,我不知道它是怎么回事。看起来,每次调用相同参数的相同方法,结果都会有所不同。

这是我修改并获得这种奇怪行为的一个javascript内置类和方法的示例:

//Inherit everything from original String class in STRING class.
class STRING extends String
{
    //Redefine behavior of original replace method.
    replace()
    {
        //Get original javascript's replace method definition from prototype
        //of this class's prototype (base class) and attach it to this
        //object's instance, and then run it and pass anything it returns
        //back to the caller.
        return this.__proto__.__proto__.replace.call(this);
    }
}
//Replace original javascript's replace method with custom replace method
//everywhere, including in string primitives.
String.prototype.replace = STRING.prototype.replace;
//Replace whole original javascript's String class with custom STRING class.
String = STRING;
//Create custom string primitive.
let a = "hello stacky";
//Call custom replace method in custom string primitive.
a.replace();

此代码的本质作用是仅通过我的自定义类和方法传递默认javascript的String类和replace类中的String方法即可。 (如代理)。

请忽略某些内容丢失,并且此代码无用,因为它什么也不做。我只是简化了它,以便能够向您显示问题。因此,我知道replace方法应该有两个参数,但是让我们暂时忽略它。即使没有参数,它也可以工作(replace方法与toString方法的工作原理相同,没有给出参数)。

在将STRING类定义为String类的扩展之后,我将replace方法复制到String原型,因为否则,只有STRING和{{1 }}对象将具有该方法,但没有String基元。

然后,我创建测试原语,并在其上调用我的自定义string方法。

这应该输出replace,因为如果您在hello stacky上调用replace方法而没有参数,则将与调用STRING方法相同。

toString方法中,以下语句应该为true,有时是,有时不是:

  1. 首先,调用replace,它返回this对象。
  2. 之后,将调用第一个STRING访问器。这应该返回该__proto__对象的原型,那是我的自定义STRING类。
  3. 接下来,调用第二个STRING访问器。这应该返回该对象的原型的原型。因此,由于__proto__对象的原型是STRING类,因此第二个STRING应该返回__proto__类的原型。那应该是原始javascript的STRING类。
  4. 接下来,调用String方法。由于第二个replace应该返回__proto__类,因此此String方法应该是原始javascript的replace方法定义。
  5. 最后,在replace方法上调用了call方法,并且向该方法提供了replace对象的上下文。这应该将原始javascript的this方法附加到此字符串,执行它,并将其结果返回到replace类中的自定义replace方法中。 然后自定义STRING方法将其从被调用方法获得的所有内容返回给调用方。因此,输出应等于“ hello stacky”。​​

但是,这并非每天都有效。每隔第二天就会按预期工作。 当它不起作用时,则为true:

  1. replace指向当前的this对象。
  2. STRING也指当前的this.__proto__对象。
  3. STRING也以某种方式引用了当前的this.__proto__.__proto__对象。
  4. STRING是指this.__proto__.__proto__.__proto__

我还尝试使用Object而非replaceString类访问super,但是它仍然无法访问正确的方法。

我发誓,昨天我执行了这段代码,并返回了this.__proto__.__proto__。 今天,相同的代码将返回hello stacky

我知道我可能在这里错过了一些东西,但是,不知道是什么。或MongoDB无法正常工作。

我真的不知道发生了什么。我发誓它昨天有效。

我明白了,在我的代码中有一行:typeError: this.__proto__.__proto__.replace is undefined:.这很棘手,因为String=STRINGSTRING的子类,这可能导致String类被获取完全清除掉,并替换为其自己的父级String类。 根据{{​​1}} STRING类是它自己的父级,因为this.__proto__.__proto__类的原型是另一个STRING类,而该STRING类的原型是{ {1}}类,而不是STRING类。因此,似乎STRING每隔一天就会成为其自己的父级。

但是,如果是这样的话,为什么它昨天仍然有效? 相同的代码有效;我测试了这种方法,并且有效。我有昨天的测试结果。

确切地说,不是我在这里写的确切代码。并非昨天的代码有效。但是,我有另一种方法的代码,自昨天以来我从未真正对其进行过修改,而昨天它仍然有效,但今天却没有。 在这里的这个示例中,我删除了99%的代码,但是保留了对该问题很重要的部分。此代码确实产生与我的原始代码相同的错误。这就是为什么我说“此”代码昨天有效。

对您来说可能重要的是我如何测试此代码。 为了进行测试,我使用了mongodb shell。

此外,重要的是要提到我正在使用mongodb 4.1.6版(即beta版),因此使用的是不稳定版本的mongo。这可能是这种奇怪行为的根源。

因此,我对您的问题是:为什么这段代码昨天可以使用,但是现在不再可用? 如果您不能回答这个问题,那么您能告诉我如何正确完成此任务吗?

任务是: 定义必须覆盖Object方法的String类的子类,并确保每个字符串实例,无论使用STRING构造函数,String构造函数或{调用replace方法时,{1}}具有相同的自定义行为。

1 个答案:

答案 0 :(得分:1)

不知道您要在此处完成什么工作-记录下来,这似乎是一个Bad Idea™-但如果必须的话,您是否考虑过使用super

class Wookie extends String {
  replace(...args) {
    return super.replace.apply(this, args);
  }
}

const wookie = new Wookie("chewbacca");
console.log(wookie.replace('c', 'b'));