Add self-used init method for constructor function?

Let's say I have a constructor function that I don't have access to. In this constructor function, I want to inject the init init method itself, which is run whenever a new instance is created from this constructor .

For example: we can say that there is a Cat constructor, but unfortunately I do not have access to it:

function Cat() {
    // ...code which I do not have access to
    // ...maybe it comes from an external file or something?
}

      

And now I can do this to create new cats:

var coolCat = new Cat();

      

Everything is fine and I have my new cat instance.

But now I want ( if I have access to the body of the Cat constructor function, which of course I didn't! ) Something like this:

function Cat() {
  this.roarOnInit = function() {
    alert(’ROOOAAAR!’);
  };
  this.roarOnInit();
}

      

... so when I do this:

var coolCat = new Cat();

      

... I actually get this cool ROAR-alert window!

I understand how to add the roarOnInit method to the Cat constructor (Cat.prototype.roarOnInit = function ...), but is there a way I can easily add a method call (which is executed when the Cat instance is created) to the constructor body?

It looks like such a trivial thing and it's probably very easy, but I just can't figure it out this afternoon. Thank you for being with me.

UPDATE

Thanks for answers! I forgot one very important thing, which means that I will not know in advance what the constructor function will be, or that name, etc. This is because I am running this through a function that takes any constructor as a parameter, and eventually returns the constructor (with its original name / prototype) back.

+3


source to share


2 answers


Let's start with the definition Cat

:

function Cat(name){
this.name=name;
}
Cat.prototype.meow=function(){alert(this.name)}

      

We can now overwrite this with a new constructor that returns the normal one Cat

, but only after our script has run:

var oldCat = Cat;
function Cat(name){
    var self=new oldCat(name);
    self.roarOnInit=function(){alert("ROOOOAAARRR")};
    self.roarOnInit();
    return self;
}

      

Now we can do new Cat("Muffin")

and it will roar and we will still have access to properties on the original prototype chain Cat

. I am showing this in an example snippet:



// just to be safe, define the original as oldCat()

function oldCat(name){
  this.name=name;
}
oldCat.prototype.meow=function(){alert(this.name)}


//var oldCat = Cat;
function Cat(name){
  var self=new oldCat(name);
  self.roarOnInit=function(){alert("ROOOOAAARRR")};
  self.roarOnInit();
  return self;
}

var coolCat = new Cat("Muffin");
coolCat.meow();
      

Run codeHide result


Now, if you want to distract this in order to accept any function, it's not too hard. We just need to do a little work with the constructor to pass the arguments. Javascript - create instance with array of arguments

function injectToConstructor(C){
    return function(){
        var self = new (C.bind.apply(C,[C].concat([].slice.call(arguments))))();
        console.log("object initiated:");
        console.log(self);
        return self;
    };
}

      

Then we can do something like:

Cat = injectToConstructor(Cat);
var coolCat = new Cat("Muffin"); // logs 2 items
coolCat.meow();

      

+1


source


This is because I run this through a function that takes any constructor as a parameter and eventually returns the constructor (with its original name / prototype).

You can not. You cannot change the behavior of a function, rather than "inject" code into it. The only way is to wrap the function i.e. decorate it , and return a new one.

In your example, it would look like this:



function makeRoarer(constr) {
    function Roar() { // new .name and .length, but that shouldn't matter
        constr.apply(this, arguments);
        this.roarOnInit();
    }
    Roar.prototype = constr.prototype;
    Roar.prototype.constructor = Roar;
    Roar.prototype.roarOnInit = function() {
        alert(’ROOOAAAR!’);
    };
    return Roar;
}

      

class Cat { … } // whatever
var a = new Cat(); // nothing
Cat = makeRoarer(Cat);
var b = new Cat(); // ROOOAAAR!

      

+1


source







All Articles