如何正确遍历 textarea 中按换行分割的字符串数组

使用 `for...in` 遍历 `textarea.value.split("\n")` 会返回数组索引而非实际行内容,导致序列化结果错误;应改用传统 `for` 循环、`for...of` 或 `foreach` 来访问每行字符串。

在处理

for (var line in textarea.value.split("\n")) {
    console.log(line); // 输出 "0", "1", "2", "3" —— 这是数组索引,不是行内容!
}

for...in 语句设计用于枚举对象的可枚举属性名(包括数组的数字索引),而非遍历数组元素。因此,textarea.value.split("\n") 返回的是类似 ["key1: ", "key2: 0", "key3: ", "key4: 0"] 的数组,而 for...in 实际迭代的是 "0", "1", "2", "3" 这些字符串形式的索引 —— 这正是你看到 {"0": "", "1": "", ...} 的根本原因。

✅ 正确做法:使用语义明确的数组遍历方式:

方案 1:传统 for 循环(兼容性最佳)

const lines = textarea.value.split("\n");
let json = "{\n";
for (let i = 0; i < lines.length; i++) {
    const line = lines[i].trim();
    if (!line) continue; // 跳过空行
    const [key, ...rest] = line.split(": ");
    const value = rest.join(": ").trim(); // 处理值中含冒号的情况
    json += `  "${key.trim()}": "${value}",\n`;
}
json = json.replace(/,\n$/, "\n}"); // 替换末尾逗号并闭合大括号

方案 2:for...of(推荐,语义清晰)

const lines = textarea.value.split("\n");
const entries = [];
for (const line of lines) {
    const trimmed = line.trim();
    if (!trimmed) continue;
    const [key, ...rest] = trimmed.split(": ");
    entries.push(`  "${key.trim()}": "${rest.join(": ").trim()}"`);
}
const json = "{\n" + entries.join(",\n") + "\n}";

方案 3:函数式写法(简洁、可读性强)

const json = "{\n" +
  textarea.v

alue .split("\n") .map(line => line.trim()) .filter(line => line) .map(line => { const [key, ...rest] = line.split(": "); return ` "${key.trim()}": "${rest.join(": ").trim()}"`; }) .join(",\n") + "\n}";

⚠️ 注意事项:

  • 始终对每行调用 .trim(),避免前后空白符干扰解析;
  • 使用 split(": ") 时需注意值本身可能含 ": "(如 "description": "A key: value example"),建议用 indexOf(": ") 或正则更稳健地分割;
  • 若原始 JSON 结构复杂,建议直接操作 JavaScript 对象而非逆向解析 textarea 文本——textarea 应仅作展示层,数据流应保持单向(对象 → 字符串 → textarea;用户修改后 → 重新解析 → 对象);
  • 现代开发中,优先使用 const/let 替代 var,避免变量提升与作用域问题。

总结:for...in 不适用于数组遍历。牢记「for...in 遍历键(索引),for...of / forEach / for (let i=0;...) 遍历值」这一原则,即可避免此类低级但高发的逻辑错误。