我通过用我自己的版本扩展原始类和通过覆盖原始类的方法来替换一些内置的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
对象将具有该方法,而没有String
原语。然后,我创建测试原语,并在其上调用我的自定义
string
方法。这应该输出
replace
,因为如果在不带参数的情况下调用hello stacky
上的replace
方法将与调用STRING
方法相同。在
toString
方法中,以下语句应该为true,有时是,有时不是:首先,调用
replace
,它返回this
对象。之后,首先调用
STRING
访问器。这应该返回该__proto__
对象的原型,这是我的自定义STRING
类。接下来,调用第二个
STRING
访问器。这应该返回该对象的原型的原型。因此,由于__proto__
对象的原型是STRING
类,因此第二个STRING
应该返回__proto__
类的原型。那应该是原始javascript的STRING
类。接下来,调用
String
方法。由于第二个replace
应该返回__proto__
类,因此该String
方法应该是原始javascript的replace
方法定义。最后,
replace
方法被称为call
方法,并且replace
对象的上下文被提供给该方法。这应将原始javascript的this
方法附加到此字符串,执行该字符串,并将其结果返回到replace
类中的自定义replace
方法中。然后,自定义
STRING
方法将其从被调用方法获得的所有内容返回给调用方。因此,输出应等于hello stacky。但是,这并非每次都起作用。当它不起作用时,以下是正确的:
replace
引用当前的this
对象。STRING
也指当前的this.__proto__
对象。STRING
也以某种方式引用当前的this.__proto__.__proto__
对象。STRING
是指this.__proto__.__proto__.__proto__
。我也尝试使用
Object
而不是replace
从String
类访问super
,但是它仍然无法访问正确的方法。昨天我执行了此代码,并返回了
this.__proto__.__proto__
。今天,相同的精确代码返回
hello stacky
。我知道我可能在这里错过了一些东西,但是,不知道是什么。或MongoDB无法正常工作。
我真的不知道发生了什么。
我明白了,在我的代码中有以下一行:
typeError: this.__proto__.__proto__.replace is undefined:.
这很棘手,因为String=STRING
是STRING
的子类,这可能导致String
类被完全清除并替换为String
类,是它自己的父母。根据
STRING
类,this.__proto__.__proto__
类是其自己的父类,因为STRING
类的原型是另一个STRING
类,并且该STRING
类的原型是STRING
类,而不是Object
类。但是,如果是这样的话,为什么它昨天仍然有效?
好吧,确切地说,不是我在这里编写的确切代码。并非昨天的代码有效。但是,我有另一种方法的代码,自昨天以来我从未真正对其进行过修改,而昨天它仍然有效,但今天却没有。
在这里的这个示例中,我删除了99%的代码,但是保留了对该问题很重要的部分。此代码确实产生与我的原始代码相同的错误。这就是为什么我说“此”代码昨天有效。
您可能要知道的重要一点是我如何测试此代码。
为了进行测试,我使用了mongodb shell。
另外,重要的是要提到我正在使用mongodb 4.1.6版(即beta版),因此使用的是不稳定版本的mongo。这可能是这种奇怪行为的根源。
因此,我对您的问题是:为什么这段代码昨天无法使用,但是今天不再可用?
如果您不能回答这个问题,那么您能告诉我应该怎么做才能正确完成此任务?
任务是:
定义必须重写
String
方法的String
类的子类,并确保每个字符串实例,无论使用replace
构造函数,STRING
构造函数或String
创建的天气如何,都具有相同的自定义行为调用""
方法时。
最佳答案
不知道您要在这里完成什么-记录下来,这似乎是一个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'));
关于javascript - 如果原始子类方法已在子类中被重写,如何访问该方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56232623/