JavaScript中addEventListener调用函数但无法更新全局变量
问题:下拉框切换后全局变量
text无法更新,字符统计不刷新 - 开发需求:通过
document.getElementById('texts')为HTML下拉框添加change事件监听,触发时调用changeTextValue函数 - 当前问题:
changeTextValue内部的console.log和条件逻辑可正常执行,但全局变量text在下拉框切换后无变化;页面加载时text初始赋值正常 - 尝试过的无效方案:不初始化
text(触发text.toLowerCase()未定义错误)、将text设为空数组并通过window访问(触发text.toLowerCase()不是函数错误)
相关代码
JavaScript代码
'use strict'; const mobyDickText=`Moby Dick text....`; const huckFinnText=`Huck Finn text....`; let dropdown = document.getElementById("texts"); let pick=dropdown.value; const title=pick; let chosenText; let text= changeTextValue(); let letterCount; let lowercaseText; document.getElementById("book-title").innerHTML = title; function changeTextValue() { pick = dropdown.value; if (pick === "huckFinnText") { chosenText = huckFinnText; console.log(chosenText); } else if (pick === "mobyDickText") { chosenText = mobyDickText; console.log(chosenText); } return chosenText; } console.log(text); document.getElementById("texts").addEventListener("change", changeTextValue); function countFunction(letter) { let letterCount=0; lowercaseText=text.toLowerCase(); for (let i=0; i<=text.length-1; i++) { if (letter === lowercaseText.charAt(i)) { letterCount++; } } return letterCount; } const a = countFunction("a"); const b = countFunction("b"); const c = countFunction("c"); const d = countFunction("d"); const e = countFunction("e"); const f = countFunction("f"); const g = countFunction("g"); const h = countFunction("h"); const i = countFunction("i"); const j = countFunction("j"); const k = countFunction("k"); const l = countFunction("l"); const m = countFunction("m"); const n = countFunction("n"); const o = countFunction("o"); const p = countFunction("p"); const q = countFunction("q"); const r = countFunction("r"); const s = countFunction("s"); const t = countFunction("t"); const u = countFunction("u"); const v = countFunction("v"); const w = countFunction("w"); const x = countFunction("x"); const y = countFunction("y"); const z = countFunction("z"); const letters = { "A": a, "B": b, "C": c, "D": d, "E": e, "F": f, "G": g, "H": h, "I": i, "J": j, "K": k, "L": l, "M": m, "N": n, "O": o, "P": p, "Q": q, "R": r, "S": s, "T": t, "U": u, "V": v, "W": w, "X": x, "Y": y, "Z": z }; let sortable = []; for (var num in letters) { sortable.push([num, letters[num]]); } const sorted=sortable.sort(function(a, b) { return b[1] - a[1]; }); let sortedNumbers = []; for (var value in sorted) { sortedNumbers.push(sorted[value][1]); } let sortedLetters = []; for (var value in sorted) { sortedLetters.push(sorted[value][0]); } for (let item=0; item<sorted.length; item++) { let strLetter = item.toString(); document.getElementById(strLetter).innerHTML = sortedLetters[item]; } for (let item=0; item<sorted.length; item++) { let strNumber = item.toString() + "n"; document.getElementById(strNumber).innerHTML = sortedNumbers[item].toLocaleString(); } let total=0; for (let item=0; item<sorted.length; item++) { total += sortedNumbers[item]; } document.getElementById("total").innerHTML = total.toLocaleString(); let percent = []; for (var num in sortedNumbers) { percent.push((sortedNumbers[num] / total) * 100); document.getElementById(num + "p").innerHTML = percent[num].toFixed(1) + "%"; }
HTML代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="styles.css"> </head> <body> <main id="main"> <form id="form"> <select id= "texts" name="texts" class="select"> <option value="mobyDickText" id="mobyDick">Moby Dick</option> <option value="huckFinnText" id="huckFinn">Huck Finn</option> </select> </form> <table class="result"> <tbody> <th class="title" colspan="3" id="book-title"></th> <tr><td id="0" class="letter"></td><td id="0n" class="number"></td><td id="0p" class="percent"></td></tr> <tr><td id="1" class="letter"></td><td id="1n" class="number"></td><td id="1p" class="percent"></td></tr> <tr><td id="2" class="letter"></td><td id="2n" class="number"></td><td id="2p" class="percent"></td></tr> <tr><td id="3" class="letter"></td><td id="3n" class="number"></td><td id="3p" class="percent"></td></tr> <tr><td id="4" class="letter"></td><td id="4n" class="number"></td><td id="4p" class="percent"></td></tr> <tr><td id="5" class="letter"></td><td id="5n" class="number"></td><td id="5p" class="percent"></td></tr> <tr><td id="6" class="letter"></td><td id="6n" class="number"></td><td id="6p" class="percent"></td></tr> <tr><td id="7" class="letter"></td><td id="7n" class="number"></td><td id="7p" class="percent"></td></tr> <tr><td id="8" class="letter"></td><td id="8n" class="number"></td><td id="8p" class="percent"></td></tr> <tr><td id="9" class="letter"></td><td id="9n" class="number"></td><td id="9p" class="percent"></td></tr> <tr><td id="10" class="letter"></td><td id="10n" class="number"></td><td id="10p" class="percent"></td></tr> <tr><td id="11" class="letter"></td><td id="11n" class="number"></td><td id="11p" class="percent"></td></tr> <tr><td id="12" class="letter"></td><td id="12n" class="number"></td><td id="12p" class="percent"></td></tr> <tr><td id="13" class="letter"></td><td id="13n" class="number"></td><td id="13p" class="percent"></td></tr> <tr><td id="14" class="letter"></td><td id="14n" class="number"></td><td id="14p" class="percent"></td></tr> <tr><td id="15" class="letter"></td><td id="15n" class="number"></td><td id="15p" class="percent"></td></tr> <tr><td id="16" class="letter"></td><td id="16n" class="number"></td><td id="16p" class="percent"></td></tr> <tr><td id="17" class="letter"></td><td id="17n" class="number"></td><td id="17p" class="percent"></td></tr> <tr><td id="18" class="letter"></td><td id="18n" class="number"></td><td id="18p" class="percent"></td></tr> <tr><td id="19" class="letter"></td><td id="19n" class="number"></td><td id="19p" class="percent"></td></tr> <tr><td id="20" class="letter"></td><td id="20n" class="number"></td><td id="20p" class="percent"></td></tr> <tr><td id="21" class="letter"></td><td id="21n" class="number"></td><td id="21p" class="percent"></td></tr> <tr><td id="22" class="letter"></td><td id="22n" class="number"></td><td id="22p" class="percent"></td></tr> <tr><td id="23" class="letter"></td><td id="23n" class="number"></td><td id="23p" class="percent"></td></tr> <tr><td id="24" class="letter"></td><td id="24n" class="number"></td><td id="24p" class="percent"></td></tr> <tr><td id="25" class="letter"></td><td id="25n" class="number"></td><td id="25p" class="percent"></td></tr> <tr><td class="footer" colspan="3" id="total"></td></tr> </tbody> </table> </main> <script src="script.js"></script> </body> </html>
核心问题与修复方案
核心问题
changeTextValue仅返回选中文本,但未将返回值赋值给全局text,下拉切换时函数执行但text未更新- 字符统计、表格渲染等逻辑仅在页面加载时执行一次,未绑定到下拉切换事件,导致页面内容不刷新
修复步骤
1. 修改changeTextValue函数,直接更新全局text
function changeTextValue() { pick = dropdown.value; // 直接给全局text赋值 text = pick === "huckFinnText" ? huckFinnText : mobyDickText; // 更新页面标题 document.getElementById("book-title").textContent = pick === "huckFinnText" ? "Huck Finn" : "Moby Dick"; // 触发重新统计和渲染 renderStats(); }
2. 封装统计与渲染逻辑为可复用函数
将原来的统计、排序、渲染代码封装成renderStats,每次切换下拉时调用:
function renderStats() { const lowercaseText = text.toLowerCase(); const letters = {}; // 优化字母统计,避免重复写26次 for (let charCode = 97; charCode <= 122; charCode++) { const letter = String.fromCharCode(charCode); let count = 0; for (let i = 0; i < text.length; i++) { if (lowercaseText[i] === letter) count++; } letters[letter.toUpperCase()] = count; } // 按数量降序排序 const sorted = Object.entries(letters).sort((a, b) => b[1] - a[1]); // 渲染字母、数量列 sorted.forEach(([letter, count], index) => { document.getElementById(index).textContent = letter; document.getElementById(`${index}n`).textContent = count.toLocaleString(); }); // 计算总数并渲染 const total = sorted.reduce((sum, [_, count]) => sum + count, 0); document.getElementById("total").textContent = total.toLocaleString(); // 渲染百分比列 sorted.forEach(([_, count], index) => { const percent = (count / total) * 100; document.getElementById(`${index}p`).textContent = `${percent.toFixed(1)}%`; }); }
3. 初始化页面状态
页面加载时调用changeTextValue和renderStats,确保初始内容正确:
// 初始化 changeTextValue(); renderStats();
4. 清理冗余代码
删除原代码中全局的a-z变量、letters对象、以及分散的排序渲染代码,只保留封装后的函数和初始化调用。
内容的提问来源于stack exchange,提问作者ivanheyman
相关产品推荐
相关产品推荐

