You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript游戏二次运行变量未初始化问题及fetch变量初始化咨询

问题分析与解决方案

你的推测方向是对的,但问题不止是变量未重置——事件重复绑定才是导致第二次游戏出错的核心原因,变量作用域的问题和它交织在一起,共同引发了错误。

核心问题拆解

  1. 事件重复绑定
    你在fetch的成功回调里绑定了.choice和.retry的点击事件,这意味着每次点击Start按钮,都会给.btn元素新增一套事件监听。第二次游戏时,点击选项会同时触发第一次和第二次绑定的回调,导致clicked和correct被多次累加,逻辑彻底混乱。

  2. 变量作用域与重置
    clicked和correct是在start点击事件内部用let声明的,每次点击Start确实会重新创建这两个变量,但旧的事件回调仍然引用第一次的变量实例。第二次游戏时,新旧回调会同时修改不同的变量副本,数据完全不对。

修复后的完整代码

var apikey = "https://opentdb.com/api.php?amount=2&type=multiple";
// 把变量提升到外层作用域,方便全局重置和访问
let clicked = 0;
let correct = 0;
// 存储当前题目数据,避免回调闭包问题
let currentQuiz = null;

// 只绑定一次事件委托,动态元素也能生效
$(".btn").on("click", ".start", function() {
  // 每次开始游戏强制重置变量
  clicked = 0;
  correct = 0;
  $(".header").text("Is fetching...");
  $(".content").text("just a moment please");
  $(".start").hide();
  $(".category").show();
  $(".difficulty").show();

  fetch(apikey)
    .then(response => response.json())
    .then(json => {
      currentQuiz = json;
      display(currentQuiz, clicked);
    });
});

$(".btn").on("click", ".choice", function() {
  if (!currentQuiz) return; // 防止未加载完成时点击

  console.log("clicked", clicked);
  correct += $(this).html() === currentQuiz.results[clicked].correct_answer ? 1 : 0;
  clicked++;
  console.log(correct);

  if (clicked === currentQuiz.results.length) {
    showresult(correct);
  } else {
    display(currentQuiz, clicked);
  }
});

$(".btn").on("click", ".retry", function() {
  document.querySelector('.btn').innerHTML = "<button class='start'>start</button>";
});

function display(json, clickedIdx) {
  const arr = [json.results[clickedIdx].correct_answer].concat(json.results[clickedIdx].incorrect_answers);
  // 先复制数组再打乱,避免原数组被多次修改导致选项重复
  const shuffledArr = shuffle([...arr]);
  
  $(".header").text("Question" + Number(clickedIdx + 1));
  $(".category").text("[category] : " + json.results[clickedIdx].category);
  $(".difficulty").text("[difficulty] : " + json.results[clickedIdx].difficulty);
  $(".content").text(json.results[clickedIdx].question);
  
  let html = "";
  for (let i = 0; i < shuffledArr.length; i++) {
    html += "<button class='choice'>" + shuffledArr[i] + "</button><br>";
  }
  document.querySelector('.btn').innerHTML = html;
}

function showresult(correctCount) {
  $(".header").text("Number of correct answers is " + correctCount);
  $(".category").hide();
  $(".difficulty").hide();
  $(".content").text("Challenge again");
  document.querySelector('.btn').innerHTML = "<button class='retry'>retry</button>";
}

function shuffle(array) {
  var currentIndex = array.length, temporaryValue, randomIndex;
  while (0 !== currentIndex) {
    randomIndex = Math.floor(Math.random() * currentIndex);
    currentIndex -= 1;
    temporaryValue = array[currentIndex];
    array[currentIndex] = array[randomIndex];
    array[randomIndex] = temporaryValue;
  }
  return array;
}

关键修改点说明

  • 事件委托优化:把.choice和.retry的事件监听移到外部,只绑定一次,避免重复绑定导致的多次触发问题。
  • 变量重置逻辑:将clicked和correct提升到外层,每次点击Start时强制重置为0,确保第二次游戏初始状态正确。
  • 题目数据存储:新增currentQuiz变量存储当前题目数据,解决原代码中闭包导致的无法访问最新数据的问题。
  • 洗牌逻辑修正:复制数组后再打乱,避免原数组被多次修改导致选项重复显示。
  • UI状态恢复:在Start点击时恢复category和difficulty的显示,避免第二次游戏时这些元素隐藏。

内容的提问来源于stack exchange,提问作者Heisenberg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 17:08:02