我试图覆盖一个类的功能:
class MyClass {
constructor() {
// more code
}
myFunction = function() {
console.log('not this')
}
}
// can't change the code above
MyClass.prototype.myFunction = function() {
console.log('it should print this')
}
new MyClass().myFunction()
但巴贝尔将上述内容汇总到此:
class MyClass {
constructor() {
// more code
this.myFunction = function () {
console.log('not this');
};
}
}
// can't change the code above
MyClass.prototype.myFunction = function () {
console.log('it should print this');
};
new MyClass().myFunction();
因为函数被定义为原始代码中的属性,所以Babel将该定义放在构造函数中。 如果我理解正确原型只包含函数,而不是所有属性。 因为构造函数在对象来自原型之后运行,所以我无法使用原型来覆盖该函数。
我的第二次尝试是覆盖构造函数:
class MyClass {
constructor() {
// more code
}
myFunction = function () {
console.log('not this')
}
}
// can't change the code above
let oldConstructor = MyClass.prototype.constructor
MyClass.prototype.constructor = function() {
// call old constructor first, it will set myFunction
oldConstructor()
// now overwrite myFunction
this.myFunction = function () {
console.log('it should print this')
}
}
new MyClass().myFunction()
好吧,试试吧...... 使用Babel进行编译,将其保存到test.js并运行:
~> node test.js
not this
我尽量让问题变得一般。关于为什么我不能在特定情况下更改类的更多背景信息:该类实际上来自我使用的库,而我使用的其他包也依赖于该库。 MeteorJS需要包来指定其依赖项的确切版本和来源,这就是我不能使用fork的原因:我必须派生依赖于这个库的每个包。
答案 0 :(得分:0)
事实上你正在改变你的课程,但是因为how javascript interpreter looks for information inside its objects而没有“取消”效果。首先是对象内部的属性,然后是原型链。
在您的第一个示例中,如果您“删除”本地属性,则更改生效。例如:
class MyClass {
constructor() {
// more code
this.myFunction = function () {
console.log('not this');
};
}
}
// can't change the code above
MyClass.prototype.myFunction = function () {
console.log('it should print this');
};
const obj = new MyClass();
delete obj.myFunction;
obj.myFunction();
答案 1 :(得分:0)
这不可能。每当您实例化Hard Reload
时,内部MyClass
都会重新定义。但不是原型链中定义的myFunction
。因此,Interpreter将首先在实例中查找方法,然后在原型链中查找。在原型链中定义myFunction
,可以使用JavaScript inheritance覆盖。
例如:
methods
答案 2 :(得分:0)
由于原始问题没有解决方案,我最终使用了这个:
class MyClass {
myFunction = function() {
console.log('not this')
}
}
class MyNewClass extends MyClass {
myFunction = function() {
console.log('should print this')
}
}
new MyNewClass().myFunction()
显然我现在总是必须使用MyNewClass,这是我真正不想要的,原始问题要求提供覆盖现有Class功能的解决方案,但这在我的情况下有效。
答案 3 :(得分:0)
你可以做的是通过在原型上放置一个getter / setter来拦截任务:
function myFunction() {
console.log('it should print this');
}
Object.defineProperty(MyClass.prototype, "myFunction", {
set(val) { /* ignore */ },
get() { return myFunction; }
});
或者,您可以decorate the constructor,但对于ES6类来说,这意味着extra precautions。