
本文介绍一个健壮的 javascript 函数,用于将标准化学式(如 "h2o"、"c6h12"、"cooh")解析为键值对形式的 json 对象,正确处理重复元素(如 "o" 在 "cooh" 中出现两次)、隐式数量(无数字默认为 1)及大小写敏感的元素符号。
本文介绍一个健壮的 javascript 函数,用于将标准化学式(如 "h2o"、"c6h12"、"cooh")解析为键值对形式的 json 对象,正确处理重复元素(如 "o" 在 "cooh" 中出现两次)、隐式数量(无数字默认为 1)及大小写敏感的元素符号。
化学式解析看似简单,实则需兼顾多种语法规则:元素符号首字母大写、次字母小写(如 "Na"、"Cl")、数字表示原子个数(可多位,如 "Ca12")、无数字时默认为 1,且同一元素可能多次出现(如 "COOH" 中的两个 "O")。原始实现失败的关键在于——它用赋值 result[key] = count 覆盖了已存在的计数,而非累加。这导致第二次遇到 "O" 时,前一次的 1 被新值 1 覆盖,最终 "O": 1,而非正确的 "O": 2。
以下是修正后的完整解析函数,具备生产就绪级鲁棒性:
function parseChemicalCompound(chemical) {
const result = {};
let currentElement = "";
let currentCount = "";
for (let i = 0; i < chemical.length; i++) {
const char = chemical[i];
// 大写字母:新元素开始
if (/[A-Z]/.test(char)) {
// 先保存上一个元素(如有)
if (currentElement !== "") {
const count = currentCount === "" ? 1 : parseInt(currentCount, 10);
result[currentElement] = (result[currentElement] ?? 0) + count;
}
currentElement = char;
currentCount = "";
}
// 小写字母:追加到当前元素(如 'a' in "Na")
else if (/[a-z]/.test(char)) {
currentElement += char;
}
// 数字:累积计数(支持多位数,如 "12")
else if (/\d/.test(char)) {
currentCount += char;
}
// 其他字符(如括号、+、- 等)暂不支持;可按需扩展或报错
else {
console.warn(`Unsupported character '${char}' at position ${i} in "${chemical}"`);
}
}
// 处理末尾未提交的元素
if (currentElement !== "") {
const count = currentCount === "" ? 1 : parseInt(currentCount, 10);
result[currentElement] = (result[currentElement] ?? 0) + count;
}
return result;
}✅ 关键改进点:
- 使用
(result[key] ?? 0) + count实现累加语义,而非覆盖,彻底解决"COOH"→{"O": 2}的核心问题; - 采用正则
/[A-Z]/和/[a-z]/替代 ASCII 范围判断,更清晰、可读性强且符合惯例; -
parseInt(count, 10)显式指定十进制,避免意外八进制解析; - 移除了冗余的
char === nextChar分支(该逻辑在标准化学式中无意义,且易引发错误); - 对非法字符仅警告不中断,便于调试与渐进增强。
? 使用示例:
console.log(parseChemicalCompound("H2O")); // { H: 2, O: 1 }
console.log(parseChemicalCompound("C6H12")); // { C: 6, H: 12 }
console.log(parseChemicalCompound("COOH")); // { C: 1, O: 2, H: 1 }
console.log(parseChemicalCompound("NaCl")); // { Na: 1, Cl: 1 }
console.log(parseChemicalCompound("Ca12")); // { Ca: 12 }⚠️ 注意事项:
- 本函数不支持带括号的复杂式(如
"Ca(OH)2"),如需处理需引入递归或栈解析; - 元素符号严格遵循 IUPAC 规范(如
"Fe"合法,"FE"或"fe"会拆分为"F"和"E"或"f"和"e",结果错误); - 若需返回标准 JSON 字符串,可后续调用
JSON.stringify(parseChemicalCompound("H2O"))。
该实现平衡了简洁性与实用性,是构建化学计算工具、教育应用或数据清洗管道的理想基础模块。


















