在 DOM / JavaScript 中将(附加)数据传递给事件处理程序的可能方式有哪些?

What are possible ways of passing (additional) data to an event-handler in DOM / JavaScript?

当 运行在 Firefox 上以开发人员模式运行时,我收到错误消息,“未捕获的类型错误:EventTarget.addEventListener:参数 2 不是对象。”

我想要做的是在传递值“rock”时使用“playRound()”函数运行。

在解决问题时,我在 playRound() 函数中放置了一个 console.log,并注意到它 运行 甚至在被告知“点击”操作之前就已完成。点击甚至不会触发任何东西。

这是我到目前为止的想法...

function computerPlay () {
  let computerSelection = '';
  let randomInt = Math.floor(Math.random() * 3);

  if (randomInt === 0) {
    computerSelection = 'Rock';
  } else if (randomInt === 1) {
    computerSelection = 'Paper';
  } else {
    computerSelection = 'Scissors';
  }
  return computerSelection;
}

function playRound (playerSelection) {
  let roundWinner = '';
  let computerSelection = computerPlay();

  if (playerSelection === computerSelection) {
    roundWinner = "It's a tie!";
  } else if (playerSelection == 'Rock' && computerSelection == 'Scissors'){
    roundWinner = "You win! Rock beats scissors!";
  } else if (playerSelection == 'Rock' && computerSelection == 'Paper'){
    roundWinner = "You lose! Paper beats rock!";
  } else if (playerSelection == 'Paper' && computerSelection == 'Rock'){
    roundWinner = "You win! Paper beats rock!";
  } else if (playerSelection == 'Paper' && computerSelection == 'Scissors'){
    roundWinner = "You lose! Scissors beats paper!";
  } else if (playerSelection == 'Scissors' && computerSelection == 'Paper'){
    roundWinner = "You win! Scissors beats paper!";
  } else if (playerSelection == 'Scissors' && computerSelection == 'Rock') {
    roundWinner = "You lose! Rock beats scissors!";
  }
  console.log('TEST');

  return roundWinner;
}

const rock = document.querySelector("#rock");
const paper = document.querySelector("#paper");
const scissors = document.querySelector("#scissors");

rock.addEventListener("click", playRound("rock"));
<button id="rock" value="rock">Rock</button>
<button id="paper" value="paper">Paper</button>
<button id="scissors" value="scissors">Scissors</button>

对于事件侦听器,您需要将函数作为第二个参数传入。目前,您传递的是方法 playRound 的调用返回的值。

将最后一行更改为:

rock.addEventListener("click", () => playRound("rock"));如果你想使用匿名的ES6箭头函数

rock.addEventListener("click", function() { return playRound("rock") }); 如果您更喜欢标准的匿名函数语法。

希望对您有所帮助!

当然要看"TEST"日志。由于在尝试向 rock 元素添加 event-listener 时调用了 playRound ... rock.addEventListener("click", playRound("rock")) ... 最内层的函数使用 playRound("rock") 执行。因此它将记录,并且它 returns 一个字符串(非常 roundWinner)。这个字符串值然后将通过例如添加为 rock 元素的处理函数。 ... rock.addEventListener("click", "It's a tie!") ...哪个原因立即失败,因为 addEventListener 的第二个参数需要是可调用函数。

一个可能的解决方案是以这样一种方式实现 handleNextRound 事件处理程序,即从主动点击的元素之一中读取玩家的选择...

function computerPlay() {
  return [
    'rock',
    'paper',
    'scissors'
  ][Math.floor(Math.random() * 3)];
}

function handleNextRound(evt) {
  const decisionMap = {
    rockscissors: "You win! Rock beats scissors!",
    rockpaper: "You lose! Paper beats rock!",
    paperrock: "You win! Paper beats rock!",
    paperscissors: "You lose! Scissors beats paper!",
    scissorspaper: "You win! Scissors beats paper!",
    scissorsrock: "You lose! Rock beats scissors!",
    scissorsscissors: "It's a tie!",
    paperpaper: "It's a tie!",
    rockrock: "It's a tie!"
  };
  const playerSelection = evt.currentTarget.value;
  const computerSelection = computerPlay();

  console.log('decision :', decisionMap[playerSelection + computerSelection]);

  // return decisionMap[playerSelection + computerSelection];
}

const rock = document.querySelector("#rock");
const paper = document.querySelector("#paper");
const scissors = document.querySelector("#scissors");

rock.addEventListener("click", handleNextRound);
paper.addEventListener("click", handleNextRound);
scissors.addEventListener("click", handleNextRound);
<button id="rock" value="rock">Rock</button>
<button id="paper" value="paper">Paper</button>
<button id="scissors" value="scissors">Scissors</button>

我认为不太受欢迎的另一种方法是 bind 玩家选择的值作为处理函数的参数 ([[BoundArguments]]) ...

function computerPlay() {
  return [
    'rock',
    'paper',
    'scissors'
  ][Math.floor(Math.random() * 3)];
}

function handleNextRoundWithBoundSelection(playerSelection, evt) {
  const decisionMap = {
    rockscissors: "You win! Rock beats scissors!",
    rockpaper: "You lose! Paper beats rock!",
    paperrock: "You win! Paper beats rock!",
    paperscissors: "You lose! Scissors beats paper!",
    scissorspaper: "You win! Scissors beats paper!",
    scissorsrock: "You lose! Rock beats scissors!",
    scissorsscissors: "It's a tie!",
    paperpaper: "It's a tie!",
    rockrock: "It's a tie!"
  };
  const computerSelection = computerPlay();

  console.log('(evt.currentTarget === this) ?', (evt.currentTarget === this));
  console.log('decision :', decisionMap[playerSelection + computerSelection]);
}

const rock = document.querySelector("#rock");
const paper = document.querySelector("#paper");
const scissors = document.querySelector("#scissors");

rock.addEventListener("click", handleNextRoundWithBoundSelection.bind(rock, 'rock'));
paper.addEventListener("click", handleNextRoundWithBoundSelection.bind(paper, 'paper'));
scissors.addEventListener("click", handleNextRoundWithBoundSelection.bind(scissors, 'scissors'));
<button id="rock">Rock</button>
<button id="paper">Paper</button>
<button id="scissors">Scissors</button>

其他人已经建议了第三个选项,...提供处理函数作为(匿名)function expression, either as arrow function 或经典...

function computerPlay() {
  return [
    'rock',
    'paper',
    'scissors'
  ][Math.floor(Math.random() * 3)];
}

function handleNextRound(playerSelection/*, evt*/) {
  const decisionMap = {
    rockscissors: "You win! Rock beats scissors!",
    rockpaper: "You lose! Paper beats rock!",
    paperrock: "You win! Paper beats rock!",
    paperscissors: "You lose! Scissors beats paper!",
    scissorspaper: "You win! Scissors beats paper!",
    scissorsrock: "You lose! Rock beats scissors!",
    scissorsscissors: "It's a tie!",
    paperpaper: "It's a tie!",
    rockrock: "It's a tie!"
  };
  const computerSelection = computerPlay();

  // console.log('(evt.currentTarget.value === "") ?', (evt.currentTarget.value === ""));
  console.log('decision :', decisionMap[playerSelection + computerSelection]);
}

const rock = document.querySelector("#rock");
const paper = document.querySelector("#paper");
const scissors = document.querySelector("#scissors");

rock.addEventListener("click", function () { handleNextRound('rock'); });
paper.addEventListener("click", (/*evt*/) => handleNextRound('paper'/*, evt*/));
scissors.addEventListener("click", () => handleNextRound('scissors'));
<button id="rock">Rock</button>
<button id="paper">Paper</button>
<button id="scissors">Scissors</button>