javascript - 如何构建具有多级功能层的代码/功能

标签 javascript function parameter-passing code-cleanup

我是编码初学者,我不知道如何处理“代码/函数结构问题”。因此,当您编写一个函数并且该函数开始具有更多从属函数时……我的意思是它开始成为一个多级函数,我不知道我应该如何构建我的代码以使其保持干净和可读。

这是一个示例代码,它是 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,它在功能上更深入:declareWinnerdisableClickOnFieldshiglightAllFields, declareWinnerOnModal.

因此,当您在主函数的一个子函数中添加一层函数时,代码确实变得不可读、太长且难以抗拒。

当我开始写入我的主 app.js 文件时,我在想什么应该是主要的 Controller 。然后我不会再深入一个级别,我会导入我的第一级功能所需的所有必要功能。在这里,我将导入函数 gameOver 所需的所有函数。

但是我应该将所有全局变量和我在 gameOver 之上词法声明的所有其他变量传递给 gameOver 然后函数定义和调用将非常长丑陋的:gameOver(global1,global2,global3,global4,...)

我导入的函数无法访问父函数的变量对象,因此我应该再次将所有变量作为参数传递给第二级函数 - 以及从属函数 - 需要。

最佳答案

But then I should pass into 'gameOver' all of the global and every other variables which I declaired lexically above gameOver and then the functions definition and call would be a really long and ugly: (gameOver(global1,global2,global3,global4,....))

您可以引入一个包含所有全局变量的游戏“状态”:

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

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

gameOver(state);

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

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

So when you have lets say an additional layer of functions in one of the sub-functions in your main function the code really gets to be unreadable, too long and overwhelming.

函数的嵌套深度不应超过一层。其中一些函数可能是辅助函数,它们只能访问外部函数的一个或两个变量,因此您可以将它们作为参数传入。所以例如你可以把这个:

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);

关于javascript - 如何构建具有多级功能层的代码/功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50783411/

相关文章:

c++ - 如何用 "float (*fSqrt)(float)"替换 "std::function<float(float) fSqrt>"?

javascript - 将使用 $.get() 呈现的部分 View 中的任何数据传递到 ContentPage

c++ - 在 C++ 中,如何将静态数组作为参数传递给对象,并在其中修改原始数组?

javascript - 条件运算符内的多个语句

javascript - jQuery:悬停多个不同的类名

javascript - 删除浏览器只读样式

javascript - MVC3,同一个页面View之间的切换

java - 将字符串数组作为参数传递给函数java

c - 将数组从函数传递到 main

python - 在 python 中将文件 x 中指定的函数作为命令行参数传递给文件 y 的最佳方法