Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rewiring a JavaScript function

Let's say I have a function named fna() that does a simple thing such as:

var fna = function(ar) {
    console.log("argument: ", ar);
    return "return value is argument too: " + ar;
}

fna() is coded by some other developer and I can't access to it. He didn't bother casting any events and when it is called, I have to be aware of it. Hopefully, his method is accessible by window.fna().

I want some additional code to be executed. Let's say, add this console.log

var fna = function(ar) {
     console.log("Hola, I am some additional stuff being rewired");
     console.log("argument:", ar);
     return "return value is argument too: " + ar;
}

And I want this to be executed even when called from fnb() by some other part of the code.

var fnb = function() {
    return fna("Bonjour, I am fnb and I call fna");
}

Here is a way I found, using the utils.rewire() method. utils is just some utility belt, and it could be added to your favorite framework as a plugin. Unfortunately, it only works on Firefox.

var utils = utils || {};
// Let's rewire a function. i.e. My.super.method()
utils.rewire = function(functionFullName, callback) {
    var rewired = window[functionFullName];
    console.log("%s() is being rewired", functionFullName)

    window[functionFullName] = function() {
        callback();
        return rewired.apply(this, arguments);
    }
}

Use it like this.

utils.rewire("fna",function(){
    console.log("Hola, I am some additional stuffs being rewired");
});

This seems to work such as shown in this jsbin, but (and here is my question:) How do I rewire obja.fna()?

var obja = {
    fna = function(ar) {
        console.log("argument:", ar);
        return "return value is argument too: " + ar;
    }
};

I cannot make it work to rewire the some.object.method() method.

Extra bonus question: Is there a more cleaner way to do this? Out-of-the-box clean concise and magic library?

like image 364
gasp Avatar asked Sep 10 '26 23:09

gasp


1 Answers

Refactor rewire into a rewireMethod function which acts on any given object:

var utils = utils || {};
utils.rewireMethod = function (obj, functionName, prefunc) {
    var original = obj[functionName];

    obj[functionName] = function () {
        prefunc();
        return original.apply(this, arguments);
    };
};

Note that rewire can now be written as:

utils.rewire = function (functionName, prefunc) {
    utils.rewireMethod(window, functionName, prefunc);
};

Then you just call it as:

utils.rewireMethod(obja, "fna", function () {
    console.log("Hola, I am some additional stuff being rewired");
});

Note that nothing special is required if you have a method like window.ideeli.Search.init(). In that case, the object is window.ideeli.Search, and the method name is init:

utils.rewireMethod(window.ideeli.Search, "init", function () {
    console.log("Oh yeah, nested objects.");
});
like image 146
Claudiu Avatar answered Sep 13 '26 11:09

Claudiu