在 JavaScript (JSLint) 中的 for 循环之外引用 "this" 元素

Reference "this" element outside of a for-loop in JavaScript (JSLint)

预先感谢您的帮助!

我正在创建一个简单的井字游戏来帮助我学习母语 JavaScript,所以我的目标是在没有 jQuery 或 [=62= 的情况下尽可能多地做] 为游戏。

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

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

Don't make functions within a loop.

当我尝试调用外部函数并传入 this 时,整个 div 创建过程就停止了,我不确定为什么。

我有什么(那个"works"):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>

不在循环内创建函数的建议仅在您在函数内引用 循环变量(或从该变量派生的东西)时才有意义(参见 JavaScript closure inside loops – simple practical example 为什么)。

但是因为你没有这样做,所以你的代码非常好,你可以继续使用它。


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

当你有一个表达式如foo(bar())时,bar将被调用first及其return值 将传递给 foo

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

但是,引擎甚至还没有走到那一步,因为执行 changeColor(this) 会抛出错误

Uncaught TypeError: Cannot read property 'style' of undefined

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

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

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

// ...

square.addEventListener('click', changeColor);

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