19

每当函数 foo() 触发时,我都需要触发函数 bar()。我无法控制函数 foo 或它是否会在未来发生变化。我经常遇到这种情况(我讨厌它)。

我编写了这个函数来将我的代码添加到函数 foo 的末尾:

function appendToFunction(fn,code){ 
if(typeof fn == 'function'){
    var fnCode = fn.toString() ;
    fnCode = fnCode.replace(/\}$/,code+"\n}") ;
    window.eval(fnCode);                    // Global scope
    return true ;
}
else{
    return false ;
}
}

例如:

appendToFunction(foo,"bar();");

这让我觉得这是一个可怕的想法——但它确实有效。请有人指出我更好(更安全)的方向。

编辑:foo不是一个特定的功能,而是我最终处理的许多功能。它们不会在页面中动态更改。但它们可能会不时更改(例如表单验证要求)。

解决方案:我选择了亚当答案的修改版本。它并不完美,但比我拥有的要好:

var oldFoo = foo ;
foo = function(){
        var result = oldFoo.apply(this, arguments);
        bar();
        return result ;
}

注意。注意 IE6/7 中一些没有.apply()方法的本机函数。

4

5 回答 5

35

您可以foo使用调用原始函数的自定义函数进行覆盖。

例如

var old_foo = foo;
foo = function() {
  old_foo();
  bar();
}

您还应该foo通过替换函数将任何参数传递给它。

于 2012-06-27T09:09:10.357 回答
7
function extend(fn,code){
  return function(){
    fn.apply(fn,arguments)
    code.apply(fn,argumnets)
  }
}

并像这样使用它:

function appendToFunction(fn,code){ 
    if(typeof fn == 'function'){
        var fnCode = fn.toString() ;
        fnCode = fnCode.replace(/\}$/,code+"\n}") ;
        window.eval(fnCode);                    // Global scope
        return true ;
    }
    else{
        return false ;
    }
}

appendToFunction = extend(appendToFunction,function(){/*some code*/});

这将在两个函数中为您提供相同的“this”

于 2012-06-27T09:05:56.433 回答
6

你可以做这样的事情:THE DEMO

function foo() {
 console.log('foo');
}

function appendToFunction(fn, callback) {
  window[fn] = (function(fn){
    return function() {
      fn();
      callback();
    }
 }(window[fn]));
}

appendToFunction('foo', function(){console.log('appended!')});

foo();
于 2012-06-27T09:09:40.653 回答
3

嗯,这也与我有关,你提到过

我经常遇到这种情况(我讨厌它)。

你介意我问这种情况在什么情况下不断发生吗?它是在公司范围内,还是在个人项目范围内?你显然有一个冷静的头脑,并且知道你所做的事情与众不同,所以我想知道是否有替代解决方案。

我问的原因是;这种方法可能会引发一系列问题。foo例如,如果失败,或者如果foo返回一个中间评估值怎么办?通过简单地附加bar到实际函数并不能保证它会执行。另一方面,预先挂起它意味着它更有可能被执行,但在我看来仍然不是一个好方法。

您是否考虑过修改功能foo?我知道这似乎是一个愚蠢的问题,但如果您在整个过程中遇到类似问题,这可能是值得的。如果您想保持抽象,您可以采用“事件处理程序”方法,从而foo触发 上的事件window,然后触发bar,这是否适用于您的情况。

或者,如果你知道foo它是什么以及它做了什么,你可以钩入它的原型(如果它是一个对象),然后适当地修改那里的代码。但是,您确实提到此功能可以更改,这可能会使此选项变得多余,但它仍然是一种可能的解决方案。

于 2012-06-27T09:05:18.210 回答
1

您可以将一些新代码附加或添加到现有函数中,例如使用以下方法合并它们:

function mergeFunctions(function1, function2, instance1, instance2, numberOfArgumentsToPassToFunc1) {
    return function() {
        var _arguments  = Array.prototype.slice.apply(arguments);
        var _arguments1 = _arguments.slice(0, numberOfArgumentsToPassToFunc1);
        var _arguments2 = _arguments.slice(numberOfArgumentsToPassToFunc1);
        var that = this;
        (function(function1, function2) {
            if (typeof function1 == "function") {
                if (typeof instance1 != "undefined") {
                    function1.apply(instance1, _arguments1);
                }
                else if (that == window) {
                    function1.apply(function1, _arguments1);
                }
                else {
                    var compare = mergeFunctions(function(){}, function(){});
                    if (that.toString() == compare.toString()) {
                        function1.apply(function1, _arguments1);
                    }
                    else {
                        function1.apply(that, _arguments1);
                    }
                }
            }
            if (typeof function2 == "function") {
                if (typeof instance2 != "undefined") {
                    function2.apply(instance2, _arguments2);
                }
                else if (that == window) {
                    function2.apply(function2, _arguments2);
                }
                else {
                    var compare = mergeFunctions(function(){}, function(){});
                    if (that.toString() == compare.toString()) {
                        function2.apply(function2, _arguments2);
                    }
                    else {
                        function2.apply(that, _arguments2);
                    }
                }
            }
        })(function1, function2);
    }
}



一个基本的例子如下:

// Original function:
var someFunction = function(){
    console.log("original content");
};

// Prepend new code:
// --------------------------------------------------------
someFunction = mergeFunctions(function() {
    console.log("--- prepended code");
}, someFunction);

// Testing:
someFunction();

// Outout:
// [Log] --- prepended code
// [Log] original content


// Append new code:
// --------------------------------------------------------
someFunction = mergeFunctions(someFunction, function() {
    console.log("appended code");
});

// Testing:
someFunction();

// Output:
// [Log] --- prepended code
// [Log] original content
// [Log] appended code



请注意,合并函数会尝试将预期的“this”应用于合并的部分,否则您只需将所需的“this”传递给它们,也可以处理相关参数。
一个更一般的例子可能如下:

function firstPart(a, b) {
    console.log("--- first part");
    console.log("'this' here is:");
    console.log(this.name);
    console.log("a: "+a);
    console.log("b: "+b);
}

function MyObject() {
    this.x = "x property of MyObject";
}

MyObject.prototype.secondPart = function (y) {
    console.log("");
    console.log("--- second part");
    console.log("'this' here is:");
    console.log(this.name);
    this.x = y;
    console.log("x: "+this.x);
}

MyObject.prototype.merged = mergeFunctions(firstPart, MyObject.prototype.secondPart, firstPart, MyObject, 2);

// Testing
var test = new MyObject();
test.merged("a parameter", "b parameter", "x parameter overrides x property of MyObject");

// Console output:
// [Log] --- first part
// [Log] 'this' here is:
// [Log] firstPart
// [Log] a: a parameter
// [Log] b: b parameter
// [Log] 
// [Log] --- second part
// [Log] 'this' here is:
// [Log] MyObject
// [Log] x: x parameter overrides x property of MyObject
于 2013-11-15T12:50:03.287 回答