最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How do I monkey patch an object's constructor function? - Stack Overflow

programmeradmin11浏览0评论

I'd like to monkey patch the constructor for this 'Controller' object. But how do I monkey patch the constructor function so I can still call the original? This is what I've tried.

// original
function Controller() {
    this._tag = 'div';
}
Controller.prototype.tag = function() {
    console.log(this._tag);
}

var c = new Controller(); 
c.tag(); // -> 'div', as expected


// patch attempt
var original = Controller;
Controller = function() {
    original.apply(this);
    this._tag = 'patched'; // patch
}

var c = new Controller();
c.tag(); // no method tag, prototype appears wiped...

I'd like to monkey patch the constructor for this 'Controller' object. But how do I monkey patch the constructor function so I can still call the original? This is what I've tried.

// original
function Controller() {
    this._tag = 'div';
}
Controller.prototype.tag = function() {
    console.log(this._tag);
}

var c = new Controller(); 
c.tag(); // -> 'div', as expected


// patch attempt
var original = Controller;
Controller = function() {
    original.apply(this);
    this._tag = 'patched'; // patch
}

var c = new Controller();
c.tag(); // no method tag, prototype appears wiped...
Share Improve this question edited Dec 16, 2011 at 18:07 Dane O'Connor asked Dec 16, 2011 at 6:11 Dane O'ConnorDane O'Connor 77.3k39 gold badges120 silver badges174 bronze badges 7
  • The grouping operator around the RHS function expression is superfluous. The "constructor" is declared inside another function, so you can't access it from outside (unless missing code makes it a property of the outer anonymous function or some other object). So if you want to "monkey patch" the constructor (whatever that means), inserting code where you have the comment is the only way. – RobG Commented Dec 16, 2011 at 6:37
  • @RobG If curious: en.wikipedia.org/wiki/Monkey_patch Its pretty straight forward to monkey patch a property or method, but because of the constructor functions special status I'm at a loss. You may be correct that this isn't possible, but I'm not sure about the reasons you state yet. I'll updated the code sample to reflect. – Dane O'Connor Commented Dec 16, 2011 at 15:03
  • Telling us how to monkey path a normal method is not a better code sample. It only makes it even harder to see what your real question is. – hugomg Commented Dec 16, 2011 at 15:56
  • couldn't you wrap the constructor and modify the object after it was created? i.e. define a function that calls the saved old constructor and then does its modification and returns the new object. this is commonly done else were with the factory pattern in python. – Dan D. Commented Dec 16, 2011 at 15:58
  • @missingno truth. Edited once more. – Dane O'Connor Commented Dec 16, 2011 at 16:10
 |  Show 2 more comments

3 Answers 3

Reset to default 9

You seem to want to do something like:

Constructor.prototype.oldTag = Constructor.prototype.tag;

Constructor.prototype.tag = function() {/* whatever */};

Now all instances get the new tag method and you can still call oldTag if you want (or put it back).

Or perhaps you want to do something like:

var oldConstructor = Constructor;

 var Constructor = function () { /* new constructor */ };
 Constructor.prototype = oldConstructor.prototype;

So now you have a new constructor with all the old methods. Or do both the above. Just use plain English to say what you want to do.

The cleaner way is not monkey patching the constructor: put the constructor logic in a separate init method and monkey patch / inherit that instead.

function Constructor(){
    this.init();
}
Constructor.prototype.init = function(){ /*...*/ };

You can also consider building objects with a builder function

function make_fancy_obj(){
    var obj = new Constructor();
    obj.foo = 'bar';
    return obj;
}

Constructor functions may optionally return a different this, which will override whatever is generated by the new statement itself - here's your example corrected and annotated:

// original
function Controller() {
    this._tag = 'div';
}
Controller.prototype.tag = function() {
    console.log(this._tag);
}

var c = new Controller(); 
c.tag(); // -> 'div', as expected


// patch attempt
var original = Controller;
Controller = function() {
    const instance = new original(...arguments); // 
发布评论

评论列表(0)

  1. 暂无评论