Append code to the end of an existing function

后端 未结 5 1984
别那么骄傲
别那么骄傲 2021-02-04 03:17

I need to trigger function bar() whenever function foo() fires. I have no control over function foo or whether it will change in the future. I have this situation regularly (and

相关标签:
5条回答
  • 2021-02-04 03:56

    You can just override foo with a custom function that calls the original.

    E.g.

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

    You should also pass any arguments foo takes into it via your replacement function.

    0 讨论(0)
  • 2021-02-04 04:07

    You could do something like this: 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();
    
    0 讨论(0)
  • 2021-02-04 04:08

    You can append or prepend some new code to an existing function just merging them using for example:

    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);
        }
    }
    



    A basic example would be the following:

    // 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
    



    Note that the merging function tries to apply the expected 'this' to the merged parts, otherwise you can just simply pass the wanted 'this' to them, as well as you can handle the relative arguments.
    A more general example could be the following:

    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
    
    0 讨论(0)
  • 2021-02-04 04:10
    function extend(fn,code){
      return function(){
        fn.apply(fn,arguments)
        code.apply(fn,argumnets)
      }
    }
    

    and use it like this:

    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 will give you the same "this" in both functions

    0 讨论(0)
  • 2021-02-04 04:16

    Hmm, this concerns me as well, you mentioned that

    I have this situation regularly (and I hate it).

    Do you mind if I ask in what scenario this keeps occurring? Is it in a corporate scale, or on a personal project scope? You've clearly got a level head on your shoulders and know that what you're doing is out of the ordinary, so I'm wondering if there is an alternatively solution.

    The reason I ask is; this approach could potentially open a can of problems. What if foo fails for example, or if foo returns a value mid evaluation? By simply appending bar to the actual function doesn't guarantee it will execute. Pre-pending it on the other hand means it's more likely to be executed, but still in my opinion isn't a good approach.

    Have you considered revising the function foo? I know this might seem like a silly question, but it might be worth it if you're encountering similar problems throughout. If you want to keep things abstracted you could adopt an "event handler" approach, whereby foo triggers an event on the window, which in turn then triggers bar, would this work in your case.

    Alternatively, if you know what foo is, and what it does, you could hook into it's prototype if it's an object, and then amend the code there appropriately. You did however mention that this function is open to change, which may make this option redundant, but it's a possible solution nonetheless.

    0 讨论(0)
提交回复
热议问题