Jesse
Jesse

Reputation: 408

Modify a prototype function from a different module

Say I want to write a plugin, a module that modifies the object exported in a different module. How do I modify one of the methods of the original object? Here's the code I'm trying to get to work. There's something fundamental I feel that I'm missing here.

server.js

var Fun = require('./fun2');

var fun = new Fun('honey');
console.log(fun.allTheBest(3));
fun.hiccup();

fun.js

var Fun = function(b) {
    this.best = b;

    this.allTheBest = function(n) {
        var theBest = '';
        for (var i = 0; i < n; i++) {
            theBest += this.best + ' ';
        }
        return theBest;
    };
};

module.exports = Fun;

fun2.js

var Fun = require('./fun');

var oldAllTheBest = Fun.prototype.allTheBest;

Fun.allTheBest = function (n) {
    console.log("I'm starting allTheBest.");
    return oldAllTheBest.apply(this, n);
};

Fun.prototype.hiccup = function() {
    console.log('Hic!');
};

module.exports = Fun;

And this is the output I get:

honey honey honey 
Hic!

But I expected this:

I'm starting allTheBest.
honey honey honey
Hic!

Upvotes: 0

Views: 2171

Answers (2)

victorkt
victorkt

Reputation: 14572

There are three problems in your code. First, as pointed by Bergi, you should overwrite the prototype function like this:

Fun.prototype.allTheBest = function(n) { /* ... */ }

Secondly, when you try to get the old definition of allTheBest in var oldAllTheBest = Fun.prototype.allTheBest; you will get undefined. That's because the definition of allTheBest in fun.js will only be created when you instantiate the Fun object via new. You should define the function via prototype instead:

fun.js

var Fun = function(b) {
    this.best = b;
}

Fun.prototype.allTheBest = function(n) {
        var theBest = '';
        for (var i = 0; i < n; i++) {
            theBest += this.best + ' ';
        }
        return theBest;
};

module.exports = Fun;

And lastly, you are calling apply incorrectly. apply takes an array of parameters.

So you either change your code to this:

return oldAllTheBest.apply(this, [n]);

or this:

return oldAllTheBest.call(this, n);

With these changes, your script will have the desired output:

victor@ubuntu:~/Documents/a$ node app.js 
I'm starting allTheBest.
honey honey honey 
Hic!

Upvotes: 2

Bergi
Bergi

Reputation: 665185

var oldAllTheBest = Fun.prototype.allTheBest;
Fun.allTheBest = function (n) {

You'll want to overwrite

Fun.prototype.allTheBest = function(n) {

Upvotes: 2

Related Questions