如何在没有临时变量的情况下扩展方法(猴子补丁)?

时间:2015-01-26 12:47:47

标签: javascript node.js

我的问题必须是错误的,因为我无法找到关于经常出现问题的现有问题。

我有一个班级Foo

var Foo = function () {
    return {
        a: function () {}
    };
};

我有另一个用Bar实例实例化的类Foo

var Bar = function (foo) {
    // Does something with foo.  
};

我希望将Foo实例扩展为Bar的工作方式:

var Bar = function (foo) {
    foo.a = function () {
        return foo.a.apply(this, arguments);
    };

    // Does something with foo.  
};

按照我的方式行事,将导致RangeError: Maximum call stack size exceeded。有没有办法在没有临时变量的情况下扩展方法本身?

这是使用额外变量的方法:

var Bar = function (foo) {
    var originala;

    originala = foo.a;

    foo.a = function () {
        return originala.apply(this, arguments);
    };

    // Does something with foo.  
};

2 个答案:

答案 0 :(得分:1)

问题:

您正在获得超出最大调用堆栈,因为您正在反复调用相同的函数(递归)。

原因:

构建Foo时,会获得一个分配给其属性a的函数。一切都很好。

接下来,构造Bar并尝试通过用您自己的对象替换对象上的函数来修改Foo.a的行为。但是,您希望在新函数体内,Foo.a仍将包含原始函数。反之亦然 - Foo.a现在包含您的新修改函数。这就是为什么当你调用它时,它会一直调用自己,直到你点击maximum stack size limit

这是因为变量的值在执行时被解析,并且新函数在被分配给Foo.a后执行得很好。此对象的原始功能将丢失。

解决方案:

使用prototypes。我不会详细介绍如何使用原型继承,因为周围有很多浮动。

  

请注意,您的方法是有效的,通常是唯一的方法。您只需要在某处保留对原始函数的引用,以便以后可以调用它。

答案 1 :(得分:0)

这在使用 classes 时变得非常容易。

class Foo {
    a(){
        return /* Something */
    }
}

class Bar extends Foo {
    a(){
        /* Do something else */
        return super.a()
    }
}

6 年前提出这个问题时,大多数浏览器(如果有)都无法做到这一点,但是 every modern browser now supports classes