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

使用HTML/CSS/JS实现动态选择器时遇TypeError报错求助

动态选择器数组操作报错排查:Cannot read properties of undefined (reading 'name')

错误原因分析

控制台抛出的Cannot read properties of undefined (reading 'name')错误,核心是代码存在数组越界访问和逻辑漏洞,具体问题如下:

  1. 循环边界错误
    多个for循环使用i <= options.length的条件,数组索引从0开始,最大有效索引是options.length - 1。当i等于options.length时,options[i]为undefined,访问其name属性就会触发报错。所有循环需将条件改为i < options.length。

  2. deleteItem函数的索引混乱问题
    执行options.splice(i, 1)后,数组长度减1,后续元素向前移位,但循环的i仍递增,会跳过下一个元素,甚至再次触发越界。需在splice后执行i--修正索引。

  3. editItem函数的未定义变量与逻辑错误

    • 函数内input和el未声明,属于全局变量污染,且input未传入参数;
    • 错误用循环索引i作为元素ID查找DOM,实际应使用数组项的id属性;
    • 逻辑上应只修改匹配元素,而非遍历所有元素。
  4. addItem函数的无效代码
    该函数未被使用,且存在两个错误:createOptions函数未定义,直接push(input)会把字符串存入数组,破坏options数组的对象结构一致性。


修复后的完整JS代码

let selector = document.querySelector(".selector");
let options = [];

let createItem = (input) => {
  if (!input) return; // 空输入直接返回,避免无效项
  let item = {};
  item.name = input;
  item.id = Math.trunc(Math.random() * 1000); // 增大随机数范围,降低ID重复概率
  options.push(item);

  let el = document.createElement("option");
  el.setAttribute("value", input);
  el.setAttribute("id", item.id);
  el.textContent = input; // 用textContent替代innerHTML更安全
  selector.appendChild(el);
};

// 初始化选项
createItem("Apple");
createItem("Pear");
createItem("Grape");
createItem("Watermelon");

// 删除函数修复
let deleteItem = (input) => {
  for (let i = 0; i < options.length; i++) { // 修正循环边界,用let声明i避免全局污染
    let indexedItem = options[i].name;
    if (indexedItem === input) {
      let el = document.getElementById(options[i].id);
      el?.remove(); // 可选链避免元素不存在时报错
      options.splice(i, 1);
      i--; // 删除后索引回退,避免跳过元素
      break; // 找到匹配项后退出循环,避免重复删除(如果有重名需求可去掉)
    }
  }
};

// 编辑函数修复
let editItem = (selectedItem, newItemName) => {
  if (!selectedItem || !newItemName) return;
  for (let i = 0; i < options.length; i++) {
    if (options[i].name === selectedItem) {
      options[i].name = newItemName;
      let el = document.getElementById(options[i].id);
      if (el) {
        el.setAttribute("value", newItemName);
        el.textContent = newItemName;
      }
      break; // 找到匹配项后退出循环
    }
  }
};

// 事件监听部分
document.querySelector(".add-btn").addEventListener("click", () => {
  let userInput = prompt("What should the new item be called?");
  createItem(userInput);
});

document.querySelector(".delete-btn").addEventListener("click", () => {
  let userInput = prompt("Which item would you like to delete?");
  deleteItem(userInput);
});

document.querySelector(".edit-btn").addEventListener("click", () => {
  let selectedItem = prompt("What item would you like to edit?");
  let newItemName = prompt("What would you like to rename it as?");
  editItem(selectedItem, newItemName); // 调用修复后的editItem函数
});

额外优化说明

  • 给createItem添加空输入判断,避免创建无效选项;
  • 增大随机ID范围,降低重复概率;
  • 用textContent替代innerHTML,避免XSS风险;
  • 用let声明循环变量i,避免全局变量污染;
  • 添加可选链el?.remove(),避免元素不存在时触发新错误;
  • 找到匹配项后添加break,优化循环效率(允许重名选项可去掉)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 22:20:35