简体   繁体   中英

How to dynamically change a function

I have a function that has already been assigned and I would like to append some additional script. When I display the function like:

var func = obj.when_clicked;
alert(func);

The following is displayed:

function object_123(){
    object_123_Action();
}

The type is a "function" and the function is executed elsewhere which I cannot change, the code is:

this.when_clicked();

I need to modify the function by appending my own code so it becomes:

function object_123(){
   object_123_Action();
   my_clicked(obj);
}

Then add that back and over write the when_clicked function.

It does work if I manually add the code like:

obj.when_clicked = function object_123(){object_123_Action();my_clicked(obj);};

However, I do not know what is in the function initially, all I want is to append the:

my_clicked(obj);

I do need the obj to be the actual object of interest which is obj.

You can wrap it:

var f = this.when_clicked;
this.when_clicked = function() {
    // Call the original
    var rv = f.apply(this, arguments);

    // your code here

    // Return the original function's return value
    return rv;
};

Function#apply calls the original with the specified this flag. arguments is provided by the JavaScript engine: It's a pseudo-array of the arguments your function was called with, so the above just passes all of them on.

Be sure to think about what it means if your function throws an exception, and catch them if you want to suppress them.

If you do this often, you can giev yourself a utility function:

function wrapFunction(f, wrapper) {
    return function() {
        var rv = f.apply(this, arguments);
        wrapper.apply(this, arguments);
        return rv;
    };
}

Then

this.when_clicked = wrapFunction(this.when_clicked, function() {
    // Your code here
});

Or if you want access to the original's return value, potentially changing it:

function wrapFunction(f, wrapper) {
    return function() {
        var rv = f.apply(this, arguments);
        rv = wrapper.call(this, rv, arguments);
        return rv;
    };
}

Then

this.when_clicked = wrapFunction(this.when_clicked, function(rv, args) {
    // Your code here, using `rv` and `args`, which is a pseudo-array

    // Potentially update `rv`

    return rv;
});

You can store your functions in an array on the object. Then, loop though the functions in another function and execute them.

var myObj = { 'myfunctions': [ ] };

and to add functions:

myObj.myFunctions.push (function () { /*function code here*/ });

Or if you already have a named function:

myObj.myFunctions.push (nameOfFunction);

And to call all the functions, use this function (don't add this function to myObj)

function executeMyFunctions (myObj) {
    for (var i = 0; i  < myObj.myFunctions.length; i++) {
        myObj.myFunctions[i]();
    }
}

Used this answer on another question of @peter. Meant to post here.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM