使用此内部对象数组

时间:2017-02-12 17:24:11

标签: javascript arrays javascript-objects

我有一个使用构造函数创建的对象数组。这是构造函数定义:

function Expander(elem, startingFlipped) {
  this.element = elem;
  this.flipped = startingFlipped;
}

(下面,rawElems只是document.getElementsByClassName('foo');

的结果

一旦DOMContentLoaded事件触发,我就会执行此操作来查找,构造新对象并将其推送到数组中:

for (var i = 0; i < rawElems.length; i++) {
  expanders[i] = new Expander(rawElems[i], false);

  expanders[i].this.element.addEventListener("click", function (event) {
    console.log("Clicked " + expanders[i].this.element);
  });
}

问题是,我不知道如何访问this的属性。这当前抛出错误:

  

未捕获的TypeError:无法读取未定义的属性“element”       在HTMLSpanElement。

这在某些方面很棒,因为这些是<span>元素(控制台记录对象,数组显示它已正确填充)。

但是因为我正在尝试这个构造函数模式,如何使用this正确引用每个对象中的元素?

1 个答案:

答案 0 :(得分:6)

表达式expanders[i].this.element表示“查找名称为expanders的{​​{1}}上的属性,然后在结果中查找名为i的属性,并且在 的结果上,查找名为this的属性。

但是您的element对象上没有名为Expander的属性。如果您要访问this处的Expander对象,只需使用该对象,就不要向其添加expanders[i]

this.

在事件处理程序中,expanders[i].element.addEventListener("click", function (event) { // ^--- No this. here console.log("Clicked " + this); // Here, use `this` -----^ }); 将引用您挂接事件的DOM元素,因此您根本无法通过this访问它。

如果您需要访问那里的扩展器,您需要给自己一个在事件发生时仍然有效的引用。您不能在当前循环中使用Expander,因为expanders[i]的值会在事件发生之前发生变化。

这部分有很多选项,在JavaScript closure inside loops – simple practical example中讨论过。最简单的方法之一是使用i代替Array.prototype.forEach

for

在ES2015(又名“ES6”)环境或更高版本中,您可以在Array.prototype.forEach.call(rawElems, function(element, index) { var expander = expanders[index] = new Expander(element, false); element.addEventListener("click", function (event) { // You can use `element` and `expander` here // If you liked, you could *not* have the `expander` variable // and use `expanders[index]` here, because unlike the `i` in // your `for` loop, the value `index` won't change. }); }); 循环中使用letfor然后for (let i = 0; i < rawElems.length; ++i) 将< / em>正常工作。 (expanders[i]let完全不同,即使它们具有相似的用途。)

或者您可以使用varFunction.prototype.bind绑定到事件处理函数,然后使用expanders[i]来引用扩展器,this(或this.element })引用元素。这样做的好处是您可以定义处理程序一次并重复使用它:

event.currentTarget