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

Electron项目TypeError: Cannot read properties of undefined (reading 'model')求助

问题分析与解决:Electron中TypeScript函数作用域导致的this指向错误

错误信息

Error occurred in handler for 'getNetworkInterfaceControllers': TypeError: Cannot read properties of undefined (reading 'model')
    at Controller.getNetworkInterfaceControllers (/home/dave/Schreibtisch/WiFi-Deauthenticator/build/controller/controller.js:15:14)
    at node:electron/js2c/browser_init:189:579
    at EventEmitter.<anonymous> (node:electron/js2c/browser_init:161:11327)
    at EventEmitter.emit (node:events:527:28)
Error occurred in handler for 'setBandSelection': TypeError: Cannot read properties of undefined (reading 'model')
    at Controller.setBandSelection (/home/dave/Schreibtisch/WiFi-Deauthenticator/build/controller/controller.js:39:14)
    at node:electron/js2c/browser_init:189:579
    at EventEmitter.<anonymous> (node:electron/js2c/browser_init:161:11327)
    at EventEmitter.emit (node:events:527:28)

问题根源

这是JavaScript/TypeScript中经典的this绑定问题:
当你把this.controller.getNetworkInterfaceControllers这类方法直接作为回调传给ipcMain.handle时,方法的this上下文会丢失,不再指向Controller实例。执行时this会切换为ipcMain的上下文或者undefined(严格模式下),因此无法读取this.model,触发报错。

同样的问题也存在于Main类的openMessageBox方法,以及其他直接传递的控制器方法中。

解决步骤

方案1:箭头函数包裹回调

在addHandlers方法中,用箭头函数包裹控制器方法,箭头函数会继承当前上下文的this,确保方法执行时指向正确的实例:

addHandlers() {
  ipcMain.handle('getNetworkInterfaceControllers', () => this.controller.getNetworkInterfaceControllers());
  ipcMain.handle('setInterfaceSelection', (event, iface) => this.controller.setInterfaceSelection(event, iface));
  ipcMain.handle('setInterfaceMac', (event, randomized) => this.controller.setInterfaceMac(event, randomized));
  ipcMain.handle('setBandSelection', (event, bandValues) => this.controller.setBandSelection(event, bandValues));
  ipcMain.handle('startScanning', () => this.controller.model.scanAccessPoints());
  ipcMain.handle('getAccessPoints', () => this.controller.getAccessPoints());
  ipcMain.handle('openMessageBox', (event, message) => this.openMessageBox(event, message));
}

方案2:bind显式绑定this

用bind方法直接把方法的this绑定到对应实例:

addHandlers() {
  ipcMain.handle('getNetworkInterfaceControllers', this.controller.getNetworkInterfaceControllers.bind(this.controller));
  ipcMain.handle('setInterfaceSelection', this.controller.setInterfaceSelection.bind(this.controller));
  ipcMain.handle('setInterfaceMac', this.controller.setInterfaceMac.bind(this.controller));
  ipcMain.handle('setBandSelection', this.controller.setBandSelection.bind(this.controller));
  ipcMain.handle('startScanning', this.controller.model.scanAccessPoints.bind(this.controller.model));
  ipcMain.handle('getAccessPoints', this.controller.getAccessPoints.bind(this.controller));
  ipcMain.handle('openMessageBox', this.openMessageBox.bind(this));
}

方案3:类方法定义为箭头函数

修改Controller和Main类,把方法定义为箭头函数,让this永久绑定到类实例:

示例(Controller类):

class Controller {
  model: Model;

  constructor(model: Model) {
    this.model = model;
  }

  public getNetworkInterfaceControllers = () => {
    this.model.scanNetworkInterfaceControllers();
    return Object.keys(this.model.networkInterfaceControllers);
  }

  // 其他方法同理改为箭头函数形式
}

这种方式一劳永逸,但会增加类实例的内存占用,适合小型项目。

额外潜在问题提示

  1. Model中networkInterfaceControllers类型错误:
    你定义它为数组NetworkInterfaceController[],但实际用对象键值对方式赋值(this.networkInterfaceControllers[address] = nic),数组应使用数字索引,此处需改成对象类型:

    networkInterfaceControllers: { [key: string]: NetworkInterfaceController };
    

    并在构造函数中初始化:

    constructor() {
      this.networkInterfaceControllers = {};
      // 其他初始化代码
    }
    

    否则会导致数组长度异常,后续遍历或访问出错。

  2. usedNetworkInterfaceController未确保初始化:
    Model中用!断言该属性非空,但如果用户未选择接口就调用扫描,会触发this.usedNetworkInterfaceController.name报错,建议添加初始化逻辑或使用可选链(?.)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 16:46:37