tl; dr :我相信在一般情况下这样做:
// My code
var wtf = Some_Class.prototype.someMethod
Some_Class.prototype.someMethod = function(parameters) {
wtf.call(this, parameters)
}
应该等同于什么都不做。但我发现事实并非如此。我哪里错了?
某人的代码有一个我感兴趣的方法:
// Somebody's code
Some_Class.prototype.someMethod = function(parameters) {
// function body
}
我想覆盖这种方法。我一直认为这样做的JavaScript方法是这样的:
// My code
var wtf = Some_Class.prototype.someMethod
Some_Class.prototype.someMethod = function(parameters) {
wtf.call(this, parameters)
// My stuff
}
我已经看过几次这样的代码,而且它通常似乎正在运作。
然而,并非在这种情况下。即使我的覆盖函数只包含对base的调用:
// My code
var wtf = Some_Class.prototype.someMethod
Some_Class.prototype.someMethod = function(parameters) {
wtf.call(this, parameters)
}
我想在这种情况下,我的代码不应该影响程序的行为,对吧?错误。每当调用此方法时,我都会得到bizzarre结果。注释掉上面的代码可以解决所有问题。
这肯定是JS中一些已知的陷阱......什么是正确的JS方法来覆盖方法以及我做错了什么?
答案 0 :(得分:1)
首先,请确保您已正确扩展第一个对象的原型,否则您可能无法访问依赖于“this”关键字的父功能。
ExtendedThing.prototype = Object.create(Thing.prototype);
使用'apply'而不是'call'允许传递原始参数而不声明它们。除非你确切知道被覆盖的方法是如何工作的,否则我建议你这样做。
ExtendedThing.prototype.do = function ()
{
return Thing.prototype.do.apply(this, arguments);
};
我创建了一个应该有用的小jsfiddle:https://jsfiddle.net/maxbilbow/z2yeuytw/4/
开发人员可以选择通过调用Object.freeze(Thing)使其实现为只读,这使得这不可能,但我在这里创建了另一个小提琴:https://jsfiddle.net/maxbilbow/b1exeaL6/3/
(function () {
const oldDo = Thing.prototype.do;
Thing.prototype.do = function () {
return oldDo.apply(this, arguments);
};
})();
建议在iffy中复制旧方法(或使用作用域)以避免错误地再次覆盖此方法。
function Thing() {
var tmp = Thing.prototype.do;
this.do = function() {
tmp.call(this);
//do some weird stuff.
};
}
上面的代码很奇怪,但它会悄悄地破坏任何覆盖。
答案 1 :(得分:0)
GOT IT对我来说这是一个令人难以置信的,不可理解的愚蠢错误。
我正在打字:
// My code
var wtf = Some_Class.prototype.someMethod
Some_Class.prototype.someMethod = function(parameters) {
wtf.call(this, parameters)
}
虽然我应该明显地打字:
// My code
var wtf = Some_Class.prototype.someMethod
Some_Class.prototype.someMethod = function(parameters) {
return wtf.call(this, parameters)
}
这可能只能通过我目前最嗜睡和循环的状态来解释。难怪如果调用者没有获得返回值,我会得到bizzarre行为。
对不起家伙。