如何使用多级功能层构建代码/功能

时间:2018-06-10 11:52:20

标签: javascript function parameter-passing code-cleanup

我是编码的初学者,我无法弄清楚如何处理'代码/功能结构问题'。所以当你编写一个函数并且函数开始有更多的从属函数时...我的意思是它开始是一个多级函数,我不知道我应该如何构造我的代码,它仍然是干净和可读的。< / p>

以下是一个示例代码,它是tic-tac-toe game

的一部分

function gameOver(gameWonObj) {

  if (gameWonObj === 'tie') {
    higlightAllFields();
    disableClickOnFields();
    declaireWinner('tie');
  } else {
    highlightWinningHits();
    disableClickOnFields();
    declaireWinner(gameWonObj.player);
  }

  function higlightAllFields() {
    allSquaresIds = ORIG_BOARD;

    for ([idOfSquare, currValue] of allSquaresIds.entries()) {
      currSquare = document.getElementById(idOfSquare);
      currSquare.style.backgroundColor = TIE_COLOR;
    }
  }

  function highlightWinningHits() {
    winningSquaresIds = WIN_COMBOS[gameWonObj.index];
    highlightColor = (gameWonObj.player === HU_PLAYERS_SIGN) ? WINNER_COLOR : LOOSER_COLOR;

    winningSquaresIds.forEach(currentId => {
      currentWinningSquare = document.getElementById(currentId);
      currentWinningSquare.style.backgroundColor = highlightColor;
    });
  }

  function disableClickOnFields() {
    CELLS.forEach(cell => {
      cell.removeEventListener('click', turnClick, false)
    })
  }

  function declaireWinner(player) {
    if (player === 'tie') {
      declaireWinnerOnModal('ITS A TIE GAME', 'blue')
    } else if (player === HU_PLAYERS_SIGN) {
      declaireWinnerOnModal('YOU WON', 'lightgreen')
    } else if (player === AI_PLAYERS_SIGN) {
      declaireWinnerOnModal('AI WON', 'red')
    }

    function declaireWinnerOnModal(message, textColor) {
      END_GAME_MODAL.style.display = 'block';
      END_GAME_MODAL.style.color = textColor;
      END_GAME_MODAL.innerHTML = `<p>${message}</p>`;
    }
  }

}

在这个示例中,我有一个主要功能:gameOver,它在功能方面更深入:declaireWinnerdisableClickOnFieldshiglightAllFields,{{1} }。

因此,当你在主函数的一个子函数中说一个额外的函数层时,代码真的变得不可读,太长而且压倒性。

当我开始写入我的主declaireWinnerOnModal文件时,我正在思考什么应该是主要的主体。然后我不会更深入一级,我将导入我的第一级功能所需的所有必要功能。在这里,我将导入函数app.js所需的所有函数。

但是我应该将gameOver传递给gameOver以上所有我在le gameOver之上声明的全局和其他变量,然后函数定义和调用将会非常冗长和丑陋:{{1 }}

我导入的函数不能访问父函数的变量对象,因此我应该再次作为参数传递所有变量,其中第二级函数 - 以及次级函数 - 需要。

1 个答案:

答案 0 :(得分:0)

  

然后我应该进入游戏“游戏”。所有全局变量和其他变量我在gameOver上声明了词法,然后函数定义和调用将是一个非常漫长和丑陋的:( gameOver(global1,global2,global3,global4,....))

你可以介绍一个游戏&#34; state&#34;包含所有全局变量:

const state = { global1, global2, global3, global4 };

然后你只需要将该状态传递给函数:

gameOver(state);

如果对象只需要一个或两个全局变量,该函数也可以对对象进行解构:

function gameOver({global1, global2 }) {
  console.log(global1);
}
  

因此,当你在主函数的一个子函数中让一个额外的函数层时,代码真的变得不可读,太长而且势不可挡。

您不应该嵌套深度超过一个级别的函数。其中一些函数可能是帮助器,只访问thr外部函数的一个或两个变量,因此您可以将它们作为参数传递。例如,您可以将其转为:

function disableClickOnFields() {
   CELLS.forEach(cell => { // Global?!
      cell.removeEventListener('click', turnClick, false) // another global?!
   })
}

分为:

/* Removes the listener on the specific event from all elements of thr collection */
function removeEventListener(collection, evt, listener) {
  for(const el of collection) {
    el.removeEventListener(evt, listener, false);
  }
}

然后可以在多个位置重复使用,并且状态可以轻松传递:

removeEventListener(state.cells, "click", handleClick);