D.R.
D.R.

Reputation: 21224

JavaScript prototypes: replace a function

I want to decorate a function of a JavaScript "class" (prototype):

SomeClass = function() { this.someVar = 5; };

SomeClass.prototype = {
    foo: function(arg) { /* do something with this.someVar */ }
}

However, I cannot change the source of SomeClass nor am I able to influence the instance creation of SomeClass instances.

Therefore I thought about doing the following:

var oldFoo = SomeClass.prototype.foo;
SomeClass.prototype.foo = function(arg) {
    console.log("Yey, decorating!");
    oldFoo(arg);
};

This seems to work fine, however, due to function scoping oldFoo cannot access someVar anymore (the this object is now window). How to overcome this issue?

Upvotes: 1

Views: 67

Answers (1)

Benjamin Gruenbaum
Benjamin Gruenbaum

Reputation: 276406

You need to delegate it correctly. What's happening is that since you're calling oldFoo like a bare function the this value is set to undefined (or the global object in non-strict mode).

Apply the method with the arguments and set the this value explicitly:

oldFoo.apply(this, arguments); // use the same `this` and same arguments as called.

Note that in order to be really correct - you also need to return the result. So in total your code should look something like:

SomeClass.prototype.foo = function(arg) {
    console.log("Yey, decorating!");
    return oldFoo.apply(this, arguments); // alternatively capture the return value
};                                        // and process it and then return it

Upvotes: 2

Related Questions