访问匿名函数中的对象值

Accessing object values within anonymous function

本文关键字:对象 函数 访问      更新时间:2023-09-26

我有一个对象(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;
    };
};

这显然是行不通的。在匿名函数中未定义currentValue。我的问题是,我需要在调用evaluatconditions()时,根据currentValue的值对传入exampleconcondition的值进行评估-因此我不能做

Thing.prototype.exampleCondition = function(value) {
    var c = this.currentValue;
    return function() {
        return c === value;
    };
};

我是一个javascript新手,但希望你们这些聪明的人能给我指出正确的方向。

在javascript中,每个函数总是根据上下文计算,上下文定义了this的值。

函数的上下文可以在调用函数时显式或隐式设置。要隐式设置上下文,必须调用如下函数:

//z will be the context, in other words, inside method: this = z
a.b.c.d...z.method();

要显式设置上下文,在Function对象的原型中有两个函数可以使用:apply和call。这两款浏览器兼容所有浏览器,所以你不会遇到问题。问题是,有了这两个,你在每次调用函数时都设置了上下文,所以如果你直接使用它们,它不会帮助你解决问题。

你必须定义一个函数,每次调用它时总是对相同的上下文求值。为此,您可以使用bind函数,在function对象原型中定义,问题是它与旧浏览器不兼容,因为它是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));
}

对于浏览器兼容性,您可以尝试以下代码。把它放在脚本的开头,你就可以确保每个浏览器都有bind函数。

另一个可能的解决方案是:

Thing.prototype.exampleCondition = function(value) {
    var self = this;
    return function() {
        return self.currentValue === value;
    };
};

问题是,在这种情况下,您没有使用上下文,而是在返回的函数中忽略它。不是使用上下文,而是用作用域中定义的一些变量替换它。为了做到这一点,你强迫每个被定义为条件函数的函数做这个小技巧。我认为第一个解决方案更好。

问题是this在每个函数内部都发生了变化。

那么,在exampleCondition返回的函数中,this将不是您的Thing实例,而是非严格模式下的window和严格模式下的undefined

因此,您可以执行

Thing.prototype.exampleCondition = function(value) {
    var that = this;
    return function() {
        return that.currentValue === value;
    };
};

或者,如果你愿意,你可以使用ES5 bind:

Thing.prototype.exampleCondition = function(value) {
    return (function() {
        return this.currentValue === value;
    }).bind(this);
};