我通过用我自己的版本通过覆盖原始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,有时是,有时不是:
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”。但是,这并非每天都有效。每隔第二天就会按预期工作。 当它不起作用时,则为true:
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
类。
根据{{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}}具有相同的自定义行为。
答案 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'));