Javascript 在构造函数中绑定方法

Javascript 在构造函数中绑定方法,javascript,prototype-programming,Javascript,Prototype Programming,我试图创建一个类,并将其传递给另一个类,但我遇到了原型的问题。我知道我可以使用bind来解决这个问题,但是我想不出一种方法可以在实例化时将原型方法绑定到它的构造函数。这给我留下了这样的印象: foo = new obj(); // has foo.method that depends on "this" being bound to obj // pass foo.method to bar, with it's context bound to foo bar = new obj2(foo.

我试图创建一个类,并将其传递给另一个类,但我遇到了原型的问题。我知道我可以使用
bind
来解决这个问题,但是我想不出一种方法可以在实例化时将原型方法绑定到它的构造函数。这给我留下了这样的印象:

foo = new obj(); // has foo.method that depends on "this" being bound to obj
// pass foo.method to bar, with it's context bound to foo
bar = new obj2(foo.method.bind(foo)); //  obj2 uses foo.method as a "callback" internally. ugly. T_T
下面是一个人为的例子:

/**
* Base horn class. To be shared by cars, clowns, braggads, etc.
*/
var Horn = (function(){
 var Horn = function (noise){
    this.noise = noise;
  };
  Horn.prototype.sound = function(){
    return "*blowing horn* " + this.noise;
  };

  return Horn; // is there a way to bind here?
})();

/**
* Base car class. Needs a horn.
*/
var Car = (function(){
  var Car = function (model, horn) {
    this.model = model;
    this.horn = horn;
  };
  Car.prototype.drive = function(){
    return "i'm driving in my " + this.model + " " + this.horn();
  };
  return Car;
})();

/*
* Visualize output
*/
var term = document.getElementById('term');
term.say = function(message){
  this.innerHTML += message + "\n";
};

// create a horn for cars. 
var carHorn = new Horn('beep beep');
term.say(carHorn.sound()); // *blowing horn* beep beep


// pass the horn to a new Acura
var acura = new Car("acura", carHorn.sound);
term.say(acura.drive()); // i'm driving in my acura *blowing horn* undefined

// Pass the horn to a prius, but bind the horn first
var prius = new Car("prius", carHorn.sound.bind(carHorn)); // whooo bind.
term.say(prius.drive()); //i'm driving in my prius *blowing horn* beep beep

我在SO上读了很多书(这篇文章很有帮助),但我似乎找不到一个优雅的方法来做到这一点


另外,如果我是以一种完全倒退的方式来做这件事,请让我知道

您可以在构造函数中绑定方法:

var Horn = function (noise){
    this.noise = noise;
    this.sound = this.sound.bind( this );
};
RHS将从原型读取,LHS将直接写入 在对象上,当您引用它时,它将在原型上形成阴影。您仍然可以使用
hornInstance.constructor.prototype.sound
Horn.prototype.sound
引用未绑定版本

但这通常是在您没有选择的情况下完成的,即在传递方法时 作为某个地方的事件侦听器。在这种情况下,您可以轻松通过
horn对象的周围。

您可以在构造函数中绑定一个方法:

var Horn = function (noise){
    this.noise = noise;
    this.sound = this.sound.bind( this );
};
RHS将从原型读取,LHS将直接写入 在对象上,当您引用它时,它将在原型上形成阴影。您仍然可以使用
hornInstance.constructor.prototype.sound
Horn.prototype.sound
引用未绑定版本

但这通常是在您没有选择的情况下完成的,即在传递方法时 作为某个地方的事件侦听器。在这种情况下,您可以轻松通过
horn对象的周围。

我通常会传递整个对象或函数输出,正如问题注释中所建议的那样。然而,你所要求的是可能的。原型中不能包含函数,每个实例需要一个单独的(绑定的)函数:

var Horn = (function(){
 var Horn = function (noise){
     this.noise = noise;
     this.sound = function(){
        return "*blowing horn* " + this.noise;
     }.bind(this); // bind here
  };

  return Horn;
})();

我通常会传递整个对象或函数输出,正如问题注释中所建议的那样。然而,你所要求的是可能的。原型中不能包含函数,每个实例需要一个单独的(绑定的)函数:

var Horn = (function(){
 var Horn = function (noise){
     this.noise = noise;
     this.sound = function(){
        return "*blowing horn* " + this.noise;
     }.bind(this); // bind here
  };

  return Horn;
})();

为什么不将
喇叭
而不是
喇叭
方法传递给
汽车
建造师?然后,您可以使用
this.horn.sound()
而不是
this.horn()
“但是我想不出一种方法在实例化时将原型方法绑定到它的构造函数”在构造函数中,您可以迭代所有原型方法并将它们绑定到实例的相同属性名,即
this[method]=this[method].bind(this)
。当然,这会为每个实例创建每个方法的新副本,这有点违背了最初使用
原型的目的。我不会这么做。@ian理想情况下
car.horn
可以是任何函数(甚至是匿名函数),所以
Car
可以在不知道函数名的情况下调用它。@NickTomlin我知道这样的东西不是我的职责,但是如果你使用“类”,为什么不在任何地方使用它们呢?当然,它可以是任何可以调用的函数,但实际上您已经定义了一个
喇叭,为什么不使用它呢?在现实生活中,在您的程序中,我认为汽车和喇叭之间存在一种“关系”。在Car.prototype.drive中,不从汽车实例调用函数,而是在创建新车时调用它(“acura”,carHorn.sound());为什么不将
Horn
,而不是
Horn
方法传递给
Car
构造函数?然后,您可以使用
this.Horn.sound()
而不是
this.Horn()
“但是我想不出在实例化时将原型方法绑定到它的构造函数的方法。”在构造函数中,您可以迭代所有原型方法,并将它们绑定到实例的相同属性名,即
this[method]=this[method].bind(this)
。当然,这会为每个实例创建每个方法的新副本,这有点违背了最初使用
原型的目的。我不会这么做。@ian理想情况下
car.horn
可以是任何函数(甚至是匿名函数),所以
Car
可以在不知道函数名的情况下调用它。@NickTomlin我知道这样的东西不是我的职责,但是如果你使用“类”,为什么不在任何地方使用它们呢?当然,它可以是任何可以调用的函数,但实际上您已经定义了一个
喇叭,为什么不使用它呢?在现实生活中,在您的程序中,我认为汽车和喇叭之间存在一种“关系”。在Car.prototype.drive中,不从汽车实例调用函数,而是在创建新车时调用它(“acura”,carHorn.sound());假设我们几乎是同步的!:)但是你的答案是否假设你仍然有一个原型方法?我不明白为什么需要它了。@bfavaretto好吧,从技术上来说,它是不需要的。但是一些人和我更喜欢减少缩进级别并保持构造函数简单。我不能反驳这一点,你的版本看起来确实更干净。比如说我们几乎是同步的!:)但是你的答案是否假设你仍然有一个原型方法?我不明白为什么需要它了。@bfavaretto好吧,从技术上来说,它是不需要的。但是我和一些人更喜欢减少缩进级别并保持构造函数简单。我不能反驳这一点,你的版本看起来确实更干净了。