Selfish
Selfish

Reputation: 6200

Change/Wrap a function from prototype

I'm writing a framework that uses wrapping of functions in order to create a debug tool. Currently, I want to report and aggregate information upon function call. I'm using the following code:

function wrap(label, cb) {
    return function () {
        report(label);
        cb.apply(this, arguments);
    }
}

And then in order to bind the debug operation I will use:

function funcToWrap (){/* Some existing function*/}

funcToWrap = wrap("ContextLabel", funcToWrap); 

Now, when funcToWrap is invoked, it is wired to go through report() method.

The requirement I have is to now change this syntax so that the wrapping is done via:

funcToWrap.wrap("ContextLabel");

Ideally, something like this would solve my issue, but this of course is illegal:

Function.prototype.time = function(label){
    var func = this;
    // The actual difference:
    this = function () { // ILLEGAL
        report(label);
        func.apply(this, arguments);
    }
};

Thank you from ahead for any insight regarding this.

Upvotes: 1

Views: 1672

Answers (2)

Bergi
Bergi

Reputation: 665256

The requirement I have is to now change this syntax so that the wrapping is done via:

funcToWrap.wrap("ContextLabel");

That's impossible. One cannot alter a function's behaviour from the outside, it's much like an immutable primitive value in that regard. The only thing you can do is to create a new function and overwrite the old one, but this overwriting has to be explicit. You could use some eval magic for that (like here), but I recommend to use an assignment like in your first example (regardless whether the wrap function is static or a Function method).

Upvotes: 1

T.J. Crowder
T.J. Crowder

Reputation: 1075249

The requirement I have is to now change this syntax so that the wrapping is done via:

funcToWrap.wrap("ContextLabel");

Unless there's a funcToWrap = at the beginning of that, you simply can't meet that requirement. There's no way to change the guts of the function, you can only do what you're doing, create a new function to take its place.

If you have a funcToWrap = at the beginning, of course, it's quite straightforward. But I take it that's not the requirement.


But if I'm mistaking the requirement, then:

Function.prototype.wrap = function wrap(label) {
    var f = this;
    return function () {
        report(label);
        return f.apply(this, arguments); // Note the added `return` here
    };
};

Usage:

funcToWrap = funcToWrap.wrap("ContextLabel");

Reasonably certain from the question, though, that A) That's not what you're looking for, and B) You could have done it if it were.

Upvotes: 2

Related Questions