将自执行init方法添加到构造函数?

时间:2015-04-22 12:58:51

标签: javascript

假设我有一个我无法访问的构造函数。在这个构造函数中,我想注入一个自执行的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实例是创建)到构造函数体?

这看起来像是一件微不足道的事情,而且它可能非常容易,但我今天下午似乎无法解决这个问题!感谢您对我的支持。

更新

感谢目前为止的答案!我确实忘记了一个非常重要的事情,那就是我事先不会知道构造函数是什么,或者它的名字等等。这是因为我通过一个接受任何函数的函数来运行它。构造函数作为参数,最终返回构造函数(带有它的原始名称/原型)。

2 个答案:

答案 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!