【问题标题】:Reference "this" element outside of a for-loop in JavaScript (JSLint)在 JavaScript (JSLint) 中的 for 循环之外引用“this”元素
【发布时间】:2017-03-01 15:06:24
【问题描述】:

提前感谢您的帮助!

我正在创建一个简单的井字游戏来帮助我学习原生 JavaScript,所以我的目标是在没有 jQuery 或 HTML/CSS 的情况下尽可能多地完成游戏。

我正在使用 for-loop 创建多个 div 元素,遵循 JSLint。我在创建div 元素的过程中附加了一个.addEventListener(),以在单击时更改特定 div 的背景颜色。

我一直在搜索 StackOverflow,试图使用 this 来引用特定的 div 点击。到目前为止,我成功的唯一方法是在我的for-loop 中使用匿名函数within。 JSLint 没有留下深刻印象,我明白了:

不要在循环中创建函数。

当我尝试调用外部函数并传入this 时,整个div 创建过程停止工作,我不知道为什么。

我所拥有的(“有效”):https://jsfiddle.net/typj2LLb/4/

// create game
var gameContainer = document.getElementById('board');
var createBoard = function() {
  'use strict';
  var index, square;
  for (index = 0; index < 9; index += 1) {
    square = document.createElement('div');
    square.className = 'tile';

    // tile event
    square.addEventListener('click', function() {
      this.style.backgroundColor = 'yellow';
    });

    gameContainer.appendChild(square);
  }
};

createBoard();
.tile {
  display: inline-block;
  height: 25vh;
  width: 30%;
  margin: 0 3px;
  border: 1px solid black;
}
<body>
  <div id="board"></div>
</body>

我认为我应该做的事情(那行不通):https://jsfiddle.net/e4mstyy9/1/

// click-event
function changeColor(specificElement) {
  'use strict';
  specificElement.style.backgroundColor = 'yellow';
}

// create game
var gameContainer = document.getElementById('board');
var createBoard = function() {
  'use strict';
  var index, square;
  for (index = 0; index < 9; index += 1) {
    square = document.createElement('div');
    square.className = 'tile';

    // tile event
    square.addEventListener('click', changeColor(this));

    gameContainer.appendChild(square);
  }
};

createBoard();
.tile {
  display: inline-block;
  height: 25vh;
  width: 30%;
  margin: 0 3px;
  border: 1px solid black;
}
<body>
  <div id="board"></div>
</body>

【问题讨论】:

  • 始终在评论中包含相关代码或您的代码。您甚至可以使用 stack sn-ps 而不是 jsfiddle 来创建内联可运行示例。
  • 啊,谢谢菲利克斯。我会确保在未来这样做。

标签: javascript for-loop this addeventlistener jslint


【解决方案1】:

仅当您在函数内引用循环变量(或从该变量派生的变量)时,不在循环内创建函数的建议才有意义(请参阅JavaScript closure inside loops – simple practical example 了解原因)。

但是由于您没有这样做,因此您的代码非常好,您可以继续使用它。


为什么第二个例子不起作用?

当你有foo(bar())这样的表达式时,bar将被调用first,它的返回值将被传递给foo

在您的代码中,您有square.addEventListener('click', changeColor(this));。这意味着首先执行changeColor,并将其返回值传递给addEventListener

但是,引擎甚至没有走那么远,因为执行 changeColor(this) 会引发错误

未捕获的类型错误:无法读取未定义的属性“样式”

这是因为您传递给changeColor (this) 的值不是DOM 元素。由于你使用的是严格模式,this 的值为undefined,所以你正在执行changeColor(undefined)

在不创建循环体中的函数的情况下解决此问题的一种方法是简单地传递 changeColor 而不是调用它(这需要我们再次使用 this):

// click-event
function changeColor() {
  this.style.backgroundColor = 'yellow';
}

// ...

square.addEventListener('click', changeColor);

这实际上是一个很好的改变,因为该函数只被创建一次并被重复使用,而不是为每个元素创建一个新的事件处理程序。

【讨论】:

  • 我们可以有 function changeColor() { this.style.backgroundColor = 'yellow'; } 并像这样传递它:square.addEventListener('click', changeColor)); jsfiddle.net/typj2LLb/7
  • @lampyridae:是的,这更有意义。我会更新帖子。
猜你喜欢
  • 2014-07-04
  • 2020-11-18
  • 2015-10-24
  • 1970-01-01
  • 1970-01-01
  • 2019-02-11
  • 2018-01-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多