如何在不同文件中使用 GAS 类,与文件加载顺序无关?

How to use GAS classes in different files, independent of file load order?

考虑以下简单示例,文件 country.gs

class Country { }

和文件文件 subcountry.gs

class SubCountry extends Country{ }

function test(){}

尝试运行 test() 我得到

ReferenceError: Country is not defined

如果我加入文件或更改加载顺序,它工作正常。

显然,我不想依赖于文件加载顺序,也不想在推送时 clasp 更改(按字母顺序排序),因此重命名文件以编译它们绝对不是一个好方法。

是否有合适的解决方案?

示例:

https://script.google.com/d/1Pipt3YN1FBGkbRRT2PyCHhugd-Xrv3zctIWYwX-cGnAjXfDckwOk7bJh/edit?usp=sharing

我可能会采用此处描述的解决方案之一

使用 clasp 并且它是 filePushOrder 选项

{
  "scriptId":"1Pipt3YN1FBGkbRRT2PyCHhugd-Xrv3zctIWYwX-cGnAjXfDckwOk7bJh",
  "filePushOrder": [
    "country.gs",
    "subcountry.gs"
  ]
}

作者示例 https://github.com/PopGoesTheWza/clasp-filePushOrder

我强制使用clasp,但至少它易于维护。

documentation

中所写

This arrangement is identical to how browsers handle multiple tags in one HTML file.

每个文件就像一个新的 <script>file content </script> 标签,它们是按照它们在 Apps 脚本编辑器中出现的顺序添加的。仅当您使用全局变量时才会出现此问题。明确不鼓励使用全局变量。

Caution: It's not best practice to rely on a specific file parse order to avoid this issue. The sequence of script file parsing can change if script files are copied, removed, renamed, or otherwise rearranged. It's better to remove any global variable dependency on function calls if possible.

Classes are infact "special functions"。您始终可以将 Class 包含在本地范围内,并在需要时按照文档中的建议进行调用。

片段:

只需将调用函数移动到局部作用域就可以了

/*subcountry.gs*/

function test(){
  /*local scope*/class SubCountry extends Country{ }
}

为了避免在全局范围内声明 class:

/*country.gs*/
var Country;

function main(){
  if (Country == undefined) Country = class Country { }
  return Country;
}
/*subcountry.gs*/

function test(){
  /*initialize class Country*/main()
  /*local scope*/class SubCountry extends Country{ }
}

构建 posted by TheMaster and the Bruce Mcpherson article shared by Alan Wells, you could try implementing your own require() 函数。

/* Code.gs */
function test() {
  const SubCountry = require("SubCountry");
  const x = new SubCountry();
}
/* SubCountry.gs */
function SubCountry() {
  const Country = require("Country");
  return class SubCountry extends Country {};
}
/* Country.gs */
function Country() {
  return class Country {};
}
/* Require.gs */
function require(moduleName) {
  const modules = {
    Country: Country,
    SubCountry: SubCountry,
  };
  
  return modules[moduleName]();
}

或者,您可以在不使用 require() 的情况下应用更直接的方法,但我发现这不太直观。

/* Code.gs */
function test() {
  const x = new (SubCountryClass())();
}
/* SubCountry.gs */
function SubCountryClass() {
  return class SubCountry extends CountryClass() {};
}
/* Country.gs */
function CountryClass() {
  return class Country {};
}

以上所有文件,对于这两种方法,都是有意按顺序显示和加载的,如果全局声明 类 会导致 ReferenceError。所以这应该完全独立于加载顺序。