我可以向 Google Apps 脚本 类 添加自定义方法吗?

Can I add custom methods to Google Apps Script classes?

我想在 Google Apps 脚本 class 上调用自定义方法,例如 SpreadsheetSheet,以及 DriveApp。 在 中,使用了一个最小的原型解决方案来向 Javascript Date() class 添加一个方法来获取周数。是否可以将相同的策略应用于 Google Apps 脚本 classes?

例如,我想为电子表格 class 创建一个自定义方法,允许根据文件夹的 ID 将电子表格移动到我的 google 驱动器中的特定文件夹。这是我尝试过的:

Spreadsheet.prototype.moveToFolder = function(folderID) {
  const file = DriveApp.getFileById(this.getId());
  const destination = DriveApp.getFolderById(folderID);
  file.moveTo(destination);
}

但是,我收到错误消息“ReferenceError: Spreadsheet is not defined”。 还有其他方法可以实现我想要的吗?

可以添加自定义方法。但是 Spreadsheet class 不能直接访问。因此,首先需要使用任何可用的方法获取 Spreadsheet class 的实例:

const Spreadsheet = SpreadsheetApp.getActive();

然后在 Spreadsheet 实例上使用 Object.getPrototypeOf() 来获取它的原型。

Object.getPrototypeOf(Spreadsheet).myMethod = function (){
  console.info("myMethod was called!")
  return true;
}

原型上定义的任何 属性 将传播到所有电子表格实例。

更新:

Object.getPrototypeOf(Spreadsheet)返回的原型对象是Object。这也可以通过记录 Spreadsheet.constructor.name 来确认。 这意味着没有用于创建电子表格实例的特殊电子表格原型或构造函数。因此,虽然您可以添加自定义方法,但它们会添加到所有对象中,例如 RangeDriveApp 以及使用 var obj = {}Object.create("Any object except null").[=23= 创建的任何对象]

鉴于 Spreadsheet 没有唯一的原型,但实际上使用 Object 的原型作为 by TheMaster, you can simply add your method to the Object 原型。

Object.prototype.moveToFolder = function(folderID) {
  const file = DriveApp.getFileById(this.getId());
  const destination = DriveApp.getFolderById(folderID);
  file.moveTo(destination);
}

由于此方法将适用于所有对象,您应该问问自己是否真的值得这样做。参见“Why is extending native objects a bad practice?

您可以创建一个新的 class 来“继承”本机方法,同时让您能够覆盖和添加新方法,而不是修改本机对象。

function main() {
  const ss = new Spreadsheet(SpreadsheetApp.getActive());
  console.log(ss._native.getName()); // MySpreadsheet
  console.log(ss.getName()); // The name is MySpreadsheet
  
  ss.moveToFolder(FOLDER_ID);
}

class Spreadsheet {
  constructor(native) {
    this._native = native;
    
    // Copy native's methods to this
    Object.getOwnPropertyNames(this._native).forEach(property => {
      this[property] = this._native[property];
    });
    
    // Override native methods
    Object.defineProperties(this, {
      'getName': {
        value: function() {
          return `The name is ${this._native.getName()}`;
        }
      }
    });
  }
  
  moveToFolder(folderId) {
    const file = DriveApp.getFileById(this.getId());
    const destination = DriveApp.getFolderById(folderId);
    file.moveTo(destination);
  }
}