for...of循环未绑定this致上下文丢失,触发Null类型错误
问题分析与解决方案
错误根源
报错 Uncaught TypeError: Cannot read properties of null (reading 'setSwitchHandlerFunc') 由三个核心问题导致:
this上下文丢失:创建ProjectItem时未绑定switchProject方法的上下文,导致调用时this指向null。- 逻辑错误:
switchProject方法错误地将ProjectItem对象传递给setSwitchHandlerFunc,而该方法预期接收切换处理函数(如另一列表的addProject)。 - 选择器拼写错误:
addProject中移动元素的选择器少了一个s,无法定位目标列表。
修复步骤
1. 绑定 switchProject 方法上下文
在 ProjectList 构造函数的循环中,将 switchProject 绑定到当前实例:
for (const pItem of pItems) { this.projects.push( new ProjectItem(pItem.id, this.switchProject.bind(this), this.type) ); }
2. 修正 switchProject 逻辑
改为移除当前项目并调用目标列表的添加方法:
switchProject(pId) { const projectToSwitch = this.projects.find(p => p.id === pId); if (!projectToSwitch) return; this.projects = this.projects.filter(p => p.id !== pId); this.switchHandler(projectToSwitch); }
3. 修正选择器拼写
在 addProject 方法中,将选择器补全为正确的复数形式:
DOMHelper.moveElement(project.id, `#${this.type}-projects ul`);
完整修复后的 JavaScript 代码
class DOMHelper { static clearEventListeners(element) { const clonedElement = element.cloneNode(true); element.replaceWith(clonedElement); return clonedElement; } static moveElement(eId, newDestSelector) { const element = document.getElementById(eId); const destElement = document.querySelector(newDestSelector); destElement.append(element); } } class Tooltip {} class ProjectItem { constructor(id, updatePListFunc, type) { this.id = id; this.updatePListHandler = updatePListFunc; this.connectSwitchBtn(type); } connectSwitchBtn(type) { const pItemElement = document.getElementById(this.id); let switchBtn = pItemElement.querySelector('button:last-of-type'); switchBtn = DOMHelper.clearEventListeners(switchBtn); switchBtn.textContent = type === 'active' ? 'Finish' : 'Activate'; switchBtn.addEventListener('click', this.updatePListHandler.bind(null, this.id)); } update(updatePListFunc, type) { this.updatePListHandler = updatePListFunc; this.connectSwitchBtn(type); } } class ProjectList { projects = []; constructor(type) { this.type = type; const pItems = document.querySelectorAll(`#${type}-projects li`); for (const pItem of pItems) { this.projects.push( new ProjectItem(pItem.id, this.switchProject.bind(this), this.type) ); } } setSwitchHandlerFunc(switchHandlerFunc) { this.switchHandler = switchHandlerFunc; } addProject(project) { this.projects.push(project); DOMHelper.moveElement(project.id, `#${this.type}-projects ul`); project.update(this.switchProject.bind(this), this.type); } switchProject(pId) { const projectToSwitch = this.projects.find(p => p.id === pId); if (!projectToSwitch) return; this.projects = this.projects.filter(p => p.id !== pId); this.switchHandler(projectToSwitch); } } class App { static init() { const activeProjectsList = new ProjectList('active') const finishedProjectsList = new ProjectList('finished'); activeProjectsList.setSwitchHandlerFunc( finishedProjectsList.addProject.bind(finishedProjectsList) ); finishedProjectsList.setSwitchHandlerFunc( activeProjectsList.addProject.bind(activeProjectsList) ); } } App.init();
内容的提问来源于stack exchange,提问作者Mr.Unforgettable
相关产品推荐
相关产品推荐

