我正在研究一些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.firstName
时sadGreet("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 + ".");
}
}
如果您不仅可以回答问题而且告诉我如何测试它,那么可以获得奖励积分!
答案 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 );