Adding code to a javascript function programmatically

那年仲夏 提交于 2019-11-26 04:07:15

问题


I\'m attempting to customize an existing JS library without modifying the original JS code. This code loads in a few external JS files which I do have access to, and what I\'d like to do is change one of the functions contained in the original file without copying and pasting the whole thing into the second JS file.
So for example, the off limits JS might have a function like this:

var someFunction = function(){
    alert(\"done\");
}

I\'d like to be able to somehow append or prepend some JS code into that function. The reason is primarily that in the original untouchable JS the function is pretty enormous and if that JS ever gets updated, the function I overwrite it with will be out of date.

I\'m not entirely sure this is possible, but I figured I\'d check.


回答1:


If someFunction is globally available, then you can cache the function, create your own, and have yours call it.

So if this is the original...

someFunction = function() {
    alert("done");
}

You'd do this...

someFunction = (function() {
    var cached_function = someFunction;

    return function() {
        // your code

        var result = cached_function.apply(this, arguments); // use .apply() to call it

        // more of your code

        return result;
    };
})();

Here's the fiddle


Notice that I use .apply to call the cached function. This lets me retain the expected value of this, and pass whatever arguments were passed in as individual arguments irrespective of how many there were.




回答2:


first store the actual function in a variable..

var oldFunction = someFunction;

then define your own:

someFunction = function(){
  // do something before
  oldFunction();
  // do something after
};



回答3:


You can make a function that calls your code, and then calls the function.

var old_someFunction = someFunction;
someFunction = function(){
    alert('Hello');
    old_someFunction();
    alert('Goodbye');
}



回答4:


I don't know if you can update the function, but depending on how it is referenced, you can make a new function in its place:

var the_old_function = someFunction;
someFunction = function () {
    /* ..My new code... */
    the_old_function();
    /* ..More of my new code.. */
}



回答5:


Also. If you want to change local context you have to recreate function. For example:

var t = function() {
    var a = 1;
};

var z = function() {
    console.log(a);
};

Now

z() // => log: undefined

Then

var ts = t.toString(),
    zs = z.toString();

ts = ts.slice(ts.indexOf("{") + 1, ts.lastIndexOf("}"));
zs = zs.slice(zs.indexOf("{") + 1, zs.lastIndexOf("}"));

var z = new Function(ts + "\n" + zs);

And

z() // => log: 1

But this is just the simplest example. It will take still a lot of work to handle arguments, comments and return value. In addition, there are still many pitfalls.
toString | slice | indexOf | lastIndexOf | new Function




回答6:


The proxy pattern (as used by user1106925) can be put inside a function. The one I wrote below works on functions that aren't in the global scope, and even on prototypes. You would use it like this:

extender(
  objectContainingFunction,
  nameOfFunctionToExtend,
  parameterlessFunctionOfCodeToPrepend,
  parameterlessFunctionOfCodeToAppend
)

In the snippet below, you can see me using the function to extend test.prototype.doIt().

// allows you to prepend or append code to an existing function
function extender (container, funcName, prepend, append) {

    (function() {

        let proxied = container[funcName];

        container[funcName] = function() {
            if (prepend) prepend.apply( this );
            let result = proxied.apply( this, arguments );
            if (append) append.apply( this );
            return result;
        };

    })();

}

// class we're going to want to test our extender on
class test {
    constructor() {
        this.x = 'instance val';
    }
    doIt (message) {
        console.log(`logged: ${message}`);
        return `returned: ${message}`;
    }
}

// extends test.prototype.doIt()
// (you could also just extend the instance below if desired)
extender(
    test.prototype, 
    'doIt', 
    function () { console.log(`prepended: ${this.x}`) },
    function () { console.log(`appended: ${this.x}`) }
);

// See if the prepended and appended code runs
let tval = new test().doIt('log this');
console.log(tval);


来源:https://stackoverflow.com/questions/9134686/adding-code-to-a-javascript-function-programmatically

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!