假设我有一个我无法访问的构造函数。在这个构造函数中,我想注入一个自执行的init方法,只要从这个构造函数创建一个新实例就会执行该方法。
例如:假设有一个Cat构造函数,但我不幸地无法访问它:
function Cat() {
// ...code which I do not have access to
// ...maybe it comes from an external file or something?
}
我现在可以做到这一点来创造新的猫:
var coolCat = new Cat();
一切都很好,我有我的新猫实例。
但现在我想要的是(,如果我可以访问Cat构造函数体,当然我没有!)这样的事情:
function Cat() {
this.roarOnInit = function() {
alert(’ROOOAAAR!’);
};
this.roarOnInit();
}
......所以当我这样做时:
var coolCat = new Cat();
......我实际上得到了那个很酷的ROAR警报框!
我确实知道如何将方法roarOnInit添加到Cat构造函数(Cat.prototype.roarOnInit = function ...)但是有一种方法可以轻松地添加对方法的调用(只要Cat实例是创建)到构造函数体?
这看起来像是一件微不足道的事情,而且它可能非常容易,但我今天下午似乎无法解决这个问题!感谢您对我的支持。
更新
感谢目前为止的答案!我确实忘记了一个非常重要的事情,那就是我事先不会知道构造函数是什么,或者它的名字等等。这是因为我通过一个接受任何函数的函数来运行它。构造函数作为参数,最终返回构造函数(带有它的原始名称/原型)。
答案 0 :(得分:1)
让我们从Cat
的定义开始:
function Cat(name){
this.name=name;
}
Cat.prototype.meow=function(){alert(this.name)}
现在,我们可以做的是用一个返回常规Cat
的新构造函数覆盖它,但只有在运行我们的脚本之后:
var oldCat = Cat;
function Cat(name){
var self=new oldCat(name);
self.roarOnInit=function(){alert("ROOOOAAARRR")};
self.roarOnInit();
return self;
}
我们现在可以new Cat("Muffin")
,它会咆哮,我们仍然可以访问原始Cat
原型链上的属性。我在一个示例代码段中显示了这个:
// 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();

现在,如果你想抽象它来接受任何功能,那就不太难了。我们只需要对构造函数做一些工作,就可以传递参数。 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;
};
}
然后我们可以做类似的事情:
Cat = injectToConstructor(Cat);
var coolCat = new Cat("Muffin"); // logs 2 items
coolCat.meow();
答案 1 :(得分:1)
这是因为我通过一个接受任何构造函数作为参数的函数来运行它,并最终返回构造函数(带有它的原始名称/原型)。
你不能真的。改变一个功能的行为是不可能的,没有办法注入"注入"代码到它。唯一的方法是包装函数,即decorate it,然后返回一个新函数。
在您的示例中,它看起来像这样:
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!