簡體   English   中英

如何將參數值從一個模塊傳遞到另一個模塊?

[英]How to pass argument value from one module to another?

我正在嘗試為 Tic Tac Toe 游戲實現功能。

  1. const "startModule" - 玩家應該能夠在開始屏幕上輸入 select X 或 O。

  2. 然后該值應分配給參數“playerChoice” ,我正試圖將其傳遞給“gameModule”。

  3. “gameModule”中,“playerChoice”參數被分配給“circleTurn”。

  4. 基於“circleTurn 值,腳本應將 css 值(“X_CLASS”或“CIRCLE_CLASS”)分配給“handleClick”function 中的“currentClass”參數。這是不起作用的地方。

我還在學習,希望得到任何幫助或指點:)

編輯:我從之前的 js 部分刪減了很多,只留下了大量信息(我希望如此)

const startModule = (() => {
  
  let xButton = document.getElementById("player-choiceX")
  let oButton = document.getElementById("player-choiceO")
  let playerChoice;
  
  const xoChoice = () => {
    
    xButton.addEventListener('click', function(e){
      playerChoice = false;
      document.getElementById("playerChoice").style.display = "none";
      console.log(playerChoice);
    })
  }
  
  return {
    xoChoice, playerChoice
  };
  
})();


const gameModule = (() => {

    const board = document.getElementById("board");
    const X_CLASS = 'x';
    const CIRCLE_CLASS = 'circle';
    const resetButton = document.getElementById("reset");
    const winningMessageElement = document.getElementById("winningMessage");
    const cellElements = document.querySelectorAll("[data-cell]");
    const winningMessageTextElement = document.querySelector("[data-winning-message-text]");
    let circleTurn = playerChoice
  
    const WINNING_COMBINATIONS = [
        [0, 1, 2],
        [3, 4, 5],
        [6, 7, 8],
        [0, 3, 6],
        [1, 4, 7],
        [2, 5, 8],
        [0, 4, 8],
        [2, 4, 6],
      ]
      
    const startGame = () => {
      
        resetButton.addEventListener('click', startGame);
        cellElements.forEach(cell => {
          cell.classList.remove(X_CLASS)
          cell.classList.remove(CIRCLE_CLASS)
          cell.removeEventListener('click', handleClick)
          cell.addEventListener('click', handleClick, {once: true})
        })
        setBoardHoverClass()
        winningMessageElement.classList.remove('show')
    }  
      
    const handleClick = (e) => {
        const cell = e.target
        const currentClass = circleTurn ? CIRCLE_CLASS : X_CLASS
        placeMark(cell, currentClass) 
        if (checkWin(currentClass)){
          endGame()
        } else if(isDraw()) {
          endGame(true)
        } else {
          swapTurns();
          setBoardHoverClass();
        }
    }
     
    }
    return {
        startGame, handleClick
    }
  
  })();
  
  startModule.xoChoice()
  gameModule.startGame()
  
  
  
  
  
  
  
  
  
  
  
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" type="text/css" href="styles.css">
    <script src="index2.js" defer></script>
    <title>TicTacToe</title>
</head>
<body>

    <div class="player-choice" id="playerChoice">
        <div class="xOrCircle">
                <div class="player-choiceX" id="player-choiceX"></div>
                <div class="player-choiceO" id="player-choiceO"></div>
        </div>
    </div>


    </div>
    <div class="board" id="board">

        <div class="cell" data-cell></div>
        <div class="cell" data-cell></div>
        <div class="cell" data-cell></div>
        <div class="cell" data-cell></div>
        <div class="cell" data-cell></div>
        <div class="cell" data-cell></div>
        <div class="cell" data-cell></div>
        <div class="cell" data-cell></div>
        <div class="cell" data-cell></div>
        
    </div>
    <div class="winning-message" id="winningMessage">
        <div data-winning-message-text></div>
        <button id="reset">Reset</button>
    </div>



</body>
</html>

所以我想指出一些關於你所擁有的東西。

為了便於解釋,我將重寫您的startModule以使其更易於理解

const startModule = (() => {

  let playerChoice;

  const xoChoice = () => {
      playerChoice = false;
  };

  return {
    xoChoice, playerChoice
  };
})();

基於此版本的startModule ,檢查以下代碼的輸出:

startModule.playerChoice; // undefined
startModule.xoChoice();
startModule.playerChoice; // undefined

好的,那playerChoice沒有變成 false 出了什么問題? 它與稱為按值傳遞和按引用傳遞的東西有關(更多信息請參見 此處

基本上,因為playerChoice被分配了一個原始值( undefined ),當它在這里返回時:

return {
  xoChoice, playerChoice
};

return 語句只返回原始值undefined ,而不是 Object 的引用。

幸運的是,有一個解決方法,即利用 Javascript 中的傳遞引用功能。

如果不是用原始值 ( undefined ) 存儲playerChoice並返回它,我們可以用模塊的必要上下文存儲一個 Object。 這應該有效,因為對象是按引用傳遞的,而不是按值傳遞的。 這個代碼看起來像這樣:

const startModule = (() => {

  let context = {
    playerChoice: undefined    
  }; // This is a JSON Object!

  const xoChoice = () => {
    context.playerChoice = false;
  };

  return {
    xoChoice, context
  };
})();

現在讓我們看一下基於此版本的 startModule 從以下代碼輸出的內容:

startModule.context.playerChoice; // undefined
startModule.xoChoice();
startModule.context.playerChoice; // false

有用! 之所以如此,是因為我們返回的是 Object ( context ),所以我們返回的是對存儲位置的引用(據我所知:)),而不是返回沒有引用的原始值(例如undefinedfalse )到存儲的地方。 所有這些意味着調用playerChoice function 時更改的xoChoice與首次調用startModule playerChoice相互關聯的。

好的,那么您如何利用此信息在模塊之間共享playerChoice的值? 為了回答這個問題,我將再次簡化gameModule以使事情更容易理解。

const startModule = (() => {
  // ... (What we previously had)
})();
const gameModule = (() => {
  let circleTurn = context.playerChoice;

  return {
    circleTurn
  };
})();

和以前一樣,讓我們運行一些代碼看看發生了什么:

startModule.context.playerChoice; // undefined
gameModule.circleTurn; // undefined

startModule.xoChoice();
startModule.context.playerChoice; // false
startModule.circleTurn; // false

所以你是 go,使用傳遞引用我們能夠將數據從一個模塊 ( startModule ) 傳輸到另一個 ( gameModule )!

歡迎提出任何其他問題,如果您願意,我可以向您展示另一種有趣的替代編碼方式。

編輯:這是有趣的(不是更好或更壞)替代方式。 使用以前的方法,您運行了一個 function,它完成了所有這些工作,返回了一個信息豐富的 JSON Object,您可以向其中檢索信息,例如正常的 JSON Object。與其讓 startModule 成為startModule的返回值,不如將 startModule 簡單地分配給startModule ,您可以JSON Object,具有做東西的功能(之前的東西)作為 Object 的值。它看起來像這樣:

const startModule = {
  playerChoice: undefined,
  xoChoice: function () {
    // 'this' references the 'startModule' Object
    this.playerChoice = false;
  }
}

如您所見, startModule現在是 JSON Object,但仍具有與以前相同的所有組件。 閱讀有關this關鍵字的信息很重要,因為它與 this alternative 密切相關。 (僅供參考,如果您使用箭頭函數,則永遠不會分配this關鍵字,因此如果您想使用this ,請確保使用 ES5 函數)。

讓我們看看下面的代碼及其 output:

startModule.playerChoice; // undefined;
startModule.xoChoice();
startModule.playerChoice; // false

一切似乎都運行良好。 雖然playerChoice最初是undefined的,但調用xoChoice成功地將值變為false

現在這個替代方案有一個小問題。 比如說當你創建startModule時你想要自動執行一些邏輯(也許你想發出 HTTPS 請求來檢查用戶的 Tic Tac Toe 連勝記錄,也許你想檢查用戶是否登錄,等等)。 為此,通常的做法是將init分配給startModule ,並將該值分配給執行初始邏輯的 function。 它看起來像這樣:

const startModule = {
  playerChoice: undefined,
  xoChoice: function () {
    // 'this' references the 'startModule' Object
    this.playerChoice = false;
  },
  init: function () {
    // do initialization stuff
    this.userLoggedIn = true;
  }
}

現在顯然,我們需要在分配startModule后立即運行startModule.init() 這是一個更優雅的解決方案:

const startModule = {
  playerChoice: undefined,
  xoChoice: function () {
    // 'this' references the 'startModule' Object
    this.playerChoice = false;
  },
  init: function () {
    // do initialization stuff
    this.userLoggedIn = true;

    return this;
  }
}.init();

在這里,我們一創建 Object 就調用init ,但是因為init返回this ,我們仍然可以將startModule分配給這個 function 調用。

現在讓我們看看gameModule的可能實現:

const gameModule = {
  board: document.getElementById("board"),
  X_CLASS: 'x',
  CIRCLE_CLASS: 'circle',
  resetButton: document.getElementById("reset"),
  winningMessageElement: document.getElementById("winningMessage"),
  cellElements: document.querySelectorAll("[data-cell]"),
  winnningMessageTextElement: document.querySelector("[data-winning-message-text]"),
  circleTurn: startModule.playerChoice, // look for the playerChoice value in the startModule Object
  WINNING_COMBINATIONS: [
    [0, 1, 2],
    [3, 4, 5],
    [6, 7, 8],
    [0, 3, 6],
    [1, 4, 7],
    [2, 5, 8],
    [0, 4, 8],
    [2, 4, 6],
  ],
  startGame: function () {
    // 'this' references the Object this function lives under
    this.resetButton.addEventListener('click', this.startGame);
    this.cellElements.forEach(cell => {
      cell.classList.remove(this.X_CLASS)
      cell.classList.remove(this.CIRCLE_CLASS)
      cell.removeEventListener('click', this.handleClick)
      cell.addEventListener('click', this.handleClick, {once: true})
    })
    setBoardHoverClass() // idk where this func comes from
    this.winningMessageElement.classList.remove('show')
  },
  handleClick: function (e) {
    // etc...
  }
}

通過此實現,我們所有的變量都存儲為鍵值對,我們使用this來引用它們所在的 Object 並檢索它們的值。 您還可以在circleTurn的值中看到我們使用startModule.playerChoicestartModule獲取playerChoice值。

我希望我知道這兩種不同實現的技術名稱,但就我個人而言,我喜歡我剛剛展示的替代方案,因為它感覺更容易擴展,而且 IMO 感覺更容易在更清晰的意義上分離邏輯。 N.netheless,你做你,這兩種選擇都非常好,並提供自己的優點和缺點。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM