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.
source to share
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();
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();
source to share
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!
source to share