"this "值,当使用Javascript中的工厂函数、模块、事件监听器和IIFE创建井字游戏时。

问题描述 投票:0回答:1

我正在做一个井字游戏,玩家轮流在棋盘上做标记。

在这个阶段,我试图让棋盘在每次点击一个方块时在玩家之间交替显示。因此,当玩家1点击棋盘时,玩家1的符号就会显示在被点击的方块上,然后轮到玩家2选择一个方块。

这是我第一次使用Immediately-Invoked Function Expressions(IIFE's)和Factory Function,我很难让这两个模块很好地结合起来。

过程和问题是这样的。

  • 一个模块生成一个有9个正方形对象的板子 然后给每个正方形对象添加一个eventListener。当点击时,eventListener会发射一个函数。
  • 这个eventListener函数应该做两件事:修改 "方块 "对象的innerHTML,以及改变当前玩家的
  • eventListener函数使用了一个 "this "变量,它应该是 "square "对象。问题就出在这里. 在控制台记录时,我发现 "this "变量是Window对象,尽管eventListener是在 "square "对象上调用的。
  • 目前的结果是函数启动了,但点击的 "square "的innerHTML没有被修改,因为对象是Window而不是 "square "对象。

我不明白为什么会出现这种情况,也很难理解模块之间如何处理对象。

我回顾了模块、IIFE和事件监听器,但似乎找不到一个很好的例子来结合所有这些并帮助我理解问题的根源。

//Gameboard array
var boardModule = (() => {

  //Select div for board
  let boardContainer = document.querySelector("#boardContainer")
  let boardArray = ["x", "o", "x", "o", "x", "o", "x", "o", "x"];

  //Module Player Selection

  const gameFunctions = (() => {

    // Onclick function for board

    let currentPlayer;

    // Selection module
    const getPlayer = () => {

      switch (currentPlayer) {
        case undefined:
          currentPlayer = 1;
        case 1:
          console.log(this);
          this.innerHTML = "PLAYER 1 SELECTION";
          return currentPlayer = 2;
        case 2:
          this.innerHTML = "PLAYER 2 SELECTION"
          return currentPlayer = 1;
      }


    };


    return {
      getPlayer
    };

  })();



  //Module: Built board with for each

  const boardGenerator = () => {

    boardArray.forEach(element => {
      let square = document.createElement("div")
      square.classList.add("squareStyle")
      square.innerHTML = element
      square.addEventListener("click", gameFunctions.getPlayer);

      //Append to board
      boardContainer.appendChild(square);

    });
  }

  //Module: Build players

  const Player = (name, mark) => {
    getname = () => name;
    getmark = () => mark;

    const welcome = person => {
      console.log(`Welcome to ${person.getname()}`)
    }

    return {
      getname,
      getmark,
      welcome
    }
  }

  player1 = Player("player1", "X");
  player2 = Player("player2", "0");

  //Module: Square Selector
  return {
    boardGenerator,
    gameFunctions
  };

})();


boardModule.boardGenerator();
html,
body {
  height: 100%;
}

* {
  font-family: Graphik Regular;
}

.container {
  height: 100%;
  padding: 0;
  margin: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

#boardContainer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  position: absolute;
  margin: 0 auto;
  width: 300px;
  height: auto;
}

.squareStyle {
  display: flex;
  height: 100px;
  width: 100px;
  background-color: red;
  position: relative;
  align-items: center;
  justify-content: center;
}
<!DOCTYPE html>
<meta charset="UTF-8">
<html lang="en">
<head>
  <link rel="stylesheet" type="text/css" href="style.css">
  </stylesheet>
  <script type="text/javascript" src="http://livejs.com/live.js"></script>
</head>
<body>
  <div class="container">
    <div id="boardContainer">
    </div>
  </div>
  <script src="script.js"></script>
</body>
</html>
javascript events module iife
1个回答
2
投票

出现这种情况是因为你使用了一个箭头函数。箭头函数总是绑定在父作用域上,在你的例子中就是 window 对象。

请看这个例子 MDN箭头功能文档:

'use strict';

var obj = { // does not create a new scope
  i: 10,
  b: () => console.log(this.i, this),
  c: function() {
    console.log(this.i, this);
  }
}

obj.b(); // prints undefined, Window {...} (or the global object)
obj.c(); // prints 10, Object {...}
© www.soinside.com 2019 - 2024. All rights reserved.