当我覆盖方法时,为什么会得到bizzarre结果?

时间:2017-09-21 18:00:01

标签: javascript override

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方法来覆盖方法以及我做错了什么?

2 个答案:

答案 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行为。

对不起家伙。