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

Google Apps Script类模式异常:依赖注入执行问题求助

Google Apps Script 类依赖注入失败问题排查与修复

核心问题

你的代码问题与Google V8引擎、.gs文件结构无关,纯粹是TocSheet构造函数的参数顺序不匹配,导致注入的依赖被分配到了错误的变量中:

  • 在UiManager.gs的start函数里,你调用new TocSheet(spreadsheetApp, propsService),传递了两个依赖对象
  • 但TocSheet.gs的构造函数定义是constructor(name, titles, spreadsheetApp, propsService),前两个参数是可选的name和titles
  • 这就导致:spreadsheetApp被赋值给了name参数,propsService被赋值给了titles参数,而真正需要依赖的spreadsheetApp和propsService参数拿到的是undefined,最终触发了默认值逻辑,重新实例化了SpreadsheetUtility,这就是你日志里看到的现象。

修复方案

方案1:调整构造函数参数顺序(把依赖参数放在最前面)

修改TocSheet.gs的构造函数,将必填的依赖参数放在可选参数之前:

class TocSheet {
  constructor(spreadsheetApp, propsService, name, titles){
    console.log("From Toc: Spreadsheet: ", spreadsheetApp, propsService)
    this.state = {};   
    this.state.name = name || "Table of Contents";
    this.spreadsheetApp = spreadsheetApp || new SpreadsheetUtility();
    this.propsService = propsService || new PropertiesServiceStorage();
    this.state.properties = {
      sheetId: null,
      titles: null,
      range:{
        headerName: "TOCHeader",
        tocName: "TOC"
    }}
    this.initialize();
  }

  // 其他方法保持不变
}

调用时保持原有代码即可:

const myToc = new TocSheet(spreadsheetApp, propsService);

方案2:使用对象解构传递参数(更推荐,彻底避免顺序问题)

修改TocSheet.gs的构造函数为对象参数形式,这样参数顺序不再重要:

class TocSheet {
  constructor({spreadsheetApp, propsService, name, titles} = {}){
    console.log("From Toc: Spreadsheet: ", spreadsheetApp, propsService)
    this.state = {};   
    this.state.name = name || "Table of Contents";
    this.spreadsheetApp = spreadsheetApp || new SpreadsheetUtility();
    this.propsService = propsService || new PropertiesServiceStorage();
    this.state.properties = {
      sheetId: null,
      titles: null,
      range:{
        headerName: "TOCHeader",
        tocName: "TOC"
    }}
    this.initialize();
  }

  // 其他方法保持不变
}

调用时传递对象参数:

const myToc = new TocSheet({spreadsheetApp, propsService});

额外潜在bug修复

除了核心问题,代码里还有几个小问题需要修正:

  1. TocSheet.setTitles方法错误:
    原代码中title.getSheetId() !== this.sheetId里的this.sheetId未定义,应该改为this.state.properties.sheetId:
    setTitles(titles = null){
      if(titles){
        this.state.properties.titles = titles
      }else{
        const sheets = this.spreadsheetApp.getSheets();
        const titles = sheets.filter(title => title.getSheetId() !== this.state.properties.sheetId);
        this.state.properties.titles = titles;
      }
    }
    
  2. UiUtil.confirmDelete方法大小写错误:
    原代码中this.ui.ButtonSet.OK_CANCEL的ui应该是uI(和构造函数里的变量名一致):
    confirmDelete() {
      const response = this.uI.alert(
        "Confirm Deletion",
        "Delete this item?",
        this.uI.ButtonSet.OK_CANCEL
      );
      // 其他逻辑保持不变
    }
    
  3. UiManager.confirmDelete函数未实例化UiUtil:
    原代码中Ui未定义,需要先实例化UiUtil:
    function confirmDelete() {
      const uiUtil = new UiUtil(getSpreadsheetApp);
      const isConfirmed = uiUtil.confirmDelete();
      if (isConfirmed) {
        removeToc(isConfirmed);
      }
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 04:07:08