使用bind强制原型函数的上下文

时间:2014-12-30 20:52:22

标签: javascript prototype-programming

我正在研究一些JavaScript代码,这些代码将用于为我们的企业级软件构建“类”(特别是View Models)的构造函数。我正在做的事情之一是建立一个代码强制的设计模式,其中实现者将明确定义他们希望由类的实例公开的函数,并且代码将它们添加到prototype的构造函数,而不是类的每个实例的属性。这当然具有以下优点:每种类型只有每个函数的一个实例,而不是每个实例的实例。

Here's a CodePen of most of my examples.

问题是在某些情况下,我正处理binding loss个问题。例如,使用此构造函数:

  function Foo(myName) {
    this.firstName = myName;
  }

  Foo.prototype.greet = function(yourName) {
    alert("Hello, " + yourName + ". I am " + this.firstName + ".");
  }

......这会奏效:

var sam = new Foo("Sam");
// Alerts "Hello, Denny. I am Sam."
sam.greet("Denny");

......但这不会:

var sad = new Foo("Sad");
// This changes the context of greet. :(
var sadGreet = sad.greet;
// Alerts "Hello, Denny. I am undefined."
sadGreet("Denny");

这是因为当我们执行var sadGreet = sad.greet时,我们正在将greet函数的上下文更改为window,因此调用this.firstNamesadGreet("Denny")不存在

因此,我提出的解决方案是使用调用该原型的属性覆盖原型,将其包装在Function.prototype.bind()中:

function Bar(myName) {
  this.firstName = myName;
  // Here's where the magic happens.
  this.greet = Bar.prototype.greet.bind(this);
}

Bar.prototype.greet = function(yourName) {
  alert("Hello, " + yourName + ". I am " + this.firstName + ".");
}

var happy = new Bar("Happy");
// Since each instance of Bar overwrites the context for greet, this will work. :)
var happyGreet = happy.greet;
// Alerts "Hello, Denny. I am Happy."
happyGreet("Denny");

我的问题是:我认为Bar效率不如Foo,但这完全取消了宣布greet为止的任何好处一个prototype方法?无论如何,它只是重复greet作为属性,或者是我bind的电话,只是为Bar.prototype.greet添加“包装”?换句话说,这实际上与Bar的上述定义完全相同吗?

function Bar(myName) {
  this.firstName = myName;
  // Here's where the magic happens.
  this.greet = function(yourName) {
    alert("Hello, " + yourName + ". I am " + this.firstName + ".");
  }
}

如果您不仅可以回答问题而且告诉我如何测试它,那么可以获得奖励积分!

1 个答案:

答案 0 :(得分:2)

Bar的效率肯定低于Foo,但在时间复杂度方面却没有。相反,它在内存消耗方面的效率较低,因为Bar的每个实例现在都有一个独特的新问候。函数对象(' bind'函数创建一个新的函数对象)。

看看你的代码,实际上有点令人费解,即使是“问候”也是如此。 Bar.prototype上的函数。相反,这也有效:

function Bar(myName) {
  this.firstName = myName;
  this.greet = greet.bind(this);
}

var greet = function(yourName) {
  alert("Hello, " + yourName + ". I am " + this.firstName + ".");
};

var happy = new Bar("Happy");
var happyGreet = happy.greet;
happyGreet("Denny");

你可以测试一下“问候”。功能与每个实例都不相同,并且问候'通过简单地尝试这个功能:

console.log( greet === happyGreet );