我有一个跟踪某个值的对象(Thing),以及一组条件:
var Thing = function(currentValue) {
this.currentValue = currentValue;
this.conditions = [];
};
条件可以添加到此列表中:
Thing.prototype.addCondition = function(condition) {
this.conditions.push(condition);
}
我希望条件采取某种功能的形式,以便我可以做到
thing.addCondition(thing.exampleCondition(valueToCheckFor));
并且可以通过
检查这些条件Thing.prototype.evaluateConditions = function() {
this.conditions.forEach(function(condition) {
if (condition()) {
//Do something
}
});
};
目前我有一个这样的条件函数:
Thing.prototype.exampleCondition = function(value) {
return function() {
return this.currentValue === value;
};
};
这显然不起作用 - 在匿名函数中未定义this.currentValue。我的问题是我需要传递给exampleCondition的值在调用evaluateConditions()时根据currentValue的值进行评估 - 因此我不能
Thing.prototype.exampleCondition = function(value) {
var c = this.currentValue;
return function() {
return c === value;
};
};
我是一个javascript noob,但希望你这些才华横溢的人能指出我正确的方向。
答案 0 :(得分:1)
在javascript中,每个函数总是根据上下文进行评估,上下文定义了 this 的值。
在调用函数时,可以显式或隐式设置函数的上下文。要隐式设置上下文,您必须调用这样的函数:
//z will be the context, in other words, inside method: this = z
a.b.c.d...z.method();
为了显式设置上下文,您可以使用的Function对象原型中有两个函数:apply and call。这两个与每个浏览器兼容,因此您不会遇到任何问题。问题在于,使用这两个,您每次调用函数时都会设置上下文,因此如果直接使用它,它将无法帮助您解决问题。
每次调用时,都必须定义一个始终根据相同的上下文进行求值的函数。为此你可以使用在Function对象原型中定义的bind函数,问题是它与旧浏览器不兼容,因为它是ECMA-262第5版的最新版本。然而,解决方案可以将每个条件函数绑定到addCondition函数中的对象:
Thing.prototype.exampleCondition = function(value) {
return function() {
return this.currentValue === value;
};
};
Thing.prototype.addCondition = function(condition) {
//The bind function will return a function that will always execute with your object as context
this.conditions.push(condition.bind(this));
}
对于浏览器兼容性问题,您可以try this code。将它放在脚本的开头,您可以确定每个浏览器都有绑定功能。
另一种可能的解决方案可能是:
Thing.prototype.exampleCondition = function(value) {
var self = this;
return function() {
return self.currentValue === value;
};
};
问题是,在这种情况下,您没有使用上下文,您在返回的函数内忽略它。您可以使用范围中定义的某个变量替换它,而不是使用上下文。为此,您将强制定义为条件函数的每个函数执行该小技巧。我认为第一种解决方案更好。
答案 1 :(得分:0)
问题是this
在每个函数内部发生了变化。
然后,在exampleCondition
返回的函数内,this
将不是您的Thing
实例,它将是window
非严格模式且{{1}在严格模式下。
因此,你可以做到
undefined
或者,如果您愿意,可以使用ES5 bind
:
Thing.prototype.exampleCondition = function(value) {
var that = this;
return function() {
return that.currentValue === value;
};
};