在forEach循环中访问它会导致未定义

时间:2013-10-18 09:00:57

标签: javascript

我在我的一个Class方法中使用forEach迭代一个数组。我需要访问forEach中类的实例,但是这个是未定义的。

var aGlobalVar = {};

(function () {

    "use strict";

  aGlobalVar.thing = function() {
      this.value = "thing";   
  }

  aGlobalVar.thing.prototype.amethod = function() {
      data.forEach(function(d) {
      console.log(d);
      console.log(this.value);
  });
}
})();

var rr = new aGlobalVar.thing();
rr.amethod(); 

我有一个小提琴,我正在这里工作:http://jsfiddle.net/NhdDS/1/

3 个答案:

答案 0 :(得分:31)

在严格模式下,如果您通过属性引用调用函数而不是而未指定this应该是什么,那么它是undefined.

forEachspec | MDN)允许您说明this应该是什么,它是您传递的第二个参数:

aGlobalVar.thing.prototype.amethod = function() {
  data.forEach(function(d) {
    console.log(d);
    console.log(this.value);
  }, this);
  // ^^^^
}

或者,2015年已将arrow functions添加到JavaScript中。由于箭头位于this附近,我们可以使用其中一个:

aGlobalVar.thing.prototype.amethod = function() {
  data.forEach(d => {
    console.log(d);
    console.log(this.value);
  });
}

答案 1 :(得分:5)

由于您使用的是严格模式,因此当调用的函数不是对象的属性时,this默认值为undefined(不是全局对象)。您应该手动存储其值:

var aGlobalVar = {};

(function () {
    "use strict";

    aGlobalVar.thing = function () {
        this.value = "thing";   
    };

    aGlobalVar.thing.prototype.amethod = function () {
        var self = this;
        data.forEach(function (element) {
          console.log(element);
          console.log(self.value);
        });
    };
})();

var rr = new aGlobalVar.thing();
rr.amethod();

如今,使用ES2015,您还可以使用arrow functions,它使用外部函数的this值:

function foo() {
  let bar = (a, b) => {
    return this;
  };

  return bar();
}

foo.call(Math); // Math

T.J。如果你不喜欢临时变量的想法,那么Crowder使用forEach的第二个参数的解决方案也很有效(ES5代码:现在几乎可以在任何浏览器中运行,除了IE8 - )。

答案 2 :(得分:0)

我需要做的是在我使用的每个forEach中添加this(请参阅https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach)。不需要在构造函数中进行绑定,因为我使用的是箭头函数。所以现在我的代码是:

resetPressed = () => {
    this.transport_options.forEach(function (transport_option) {
        this.pressed_percentages.forEach(function (percentage) {
            filters[transport_option][percentage] = false;
        }, this)
    }, this);

    filters.isFilterActive = false;
    this.setState({
        filtersState: filters,
        opacity: filters.isFilterActive ? 1 : 0.5
    });

}


<TouchableHighlight
    underlayColor={'transparent'}
    onPress={this.resetPressed}
    style={styles.iconView}>