22

我在哪里可以阅读有关 GS 文件的执行顺序规则的文档?

为了确定问题的大小,我创建了两个微不足道的对象,每个对象都在自己的文件中。

1_文件.gs

var ObjB = new Object();
ObjB.sayName = "[" + ObjA.sayName + "]";

0_文件.gs

var ObjA = new Object();
ObjA.sayName = " I'm A ";

一个电话如...

Logger.log(ObjA.sayName + " : " + ObjB.sayName);

...得到错误...

TypeError: Cannot read property "sayName" from undefined.

如果我将代码从 1_File.gs 移动到 0_File.gs,反之亦然,则没有错误,并且日志显示正确...

我是A:[我是A]

将 0_File.gs 重命名为 2_File.gs 也不会影响执行顺序,因此我假设该顺序取决于首先创建哪个文件。

是否没有“包含”或“导入”的概念可以让我明确执行顺序?

4

7 回答 7

12

我在哪里可以阅读有关 GS 文件的执行顺序规则的文档?

没有这样的文档,我认为不会在任何时候发布。同样,C++ 中静态变量的初始化顺序也是未定义的,取决于编译器/链接器。

是否没有“包含”或“导入”的概念可以让我明确执行顺序?

是的,没有“包含”、“导入”甚至“模块”,但有

还有一个解决方法是使用闭包。贝娄是一个示例代码。通过执行测试功能,日志包含c.d. 这个想法是在所有gs文件中都有一个以init. 在这些函数中,所有全局变量都被实例化。匿名闭包在Code.gs文件实例化期间执行并调用所有文件的所有“init”函数gs

代码.gs

var c;

function callAllInits_() {
  var keys = Object.keys(this);
  for (var i = 0; i < keys.length; i++) {
    var funcName = keys[i];
    if (funcName.indexOf("init") == 0) {
      this[funcName].call(this);
    }
  }
}

(function() {
  callAllInits_();
  c = { value : 'c.' + d.value };
})();

function test() {
  Logger.log(c.value);
}

d.gs

var d;

function initD() {
  d = { value : 'd' };
};
于 2012-10-02T17:25:59.727 回答
3

我通过在每个文件中创建一个类并确保每个类都在原始文件中实例化Code.gs(我将其重命名为_init.gs)来解决这个问题。实例化每个类作为一种形式,include并确保在执行任何操作之前一切都到位。

_init.gs

// These instances can now be referred to in all other files
var Abc  = new _Abc();
var Menu = new _Menu();
var Xyz  = new _Xyz();
var Etc  = new _Etc();

// We need the global context (this) in order to dynamically add functions to it
Menu.createGlobalFunctions(this);

function onInstall(e) {
  onOpen(e);
}

function onOpen(e) {
  Menu.build();
}

类通常如下所示:

menu.gs

function _Menu() {
  this.build = function() {
    ...
  }

  ...
}
于 2015-11-03T19:55:51.463 回答
2

如果您有多个继承级别,则需要为 init 函数命名,如init000Fooinit010Barinit020Baz,然后在执行之前按名称对 init 函数进行排序。这将确保init000Foo首先被评估,然后Bar是 ,然后是Baz

function callAllInits() {
  var keys = Object.keys(this);
  var inits = new Array();
  for (var i = 0; i < keys.length; i += 1) {
    var funcName = keys[i];
    if (funcName.indexOf("init") == 0) {
      inits.push(funcName);
    }
  }

  inits.sort();
  for (var i = 0; i < inits.length; i += 1) {
    // To see init order:
    // Logger.log("Initializing " + inits[i]);
    this[inits[i]].call(this);
  }
}
于 2018-03-26T06:56:52.193 回答
1

其他答案(即不要编写任何引用其他文件中的对象的顶级代码)描述了避免此问题的理想方法。但是,如果您已经编写了很多代码并且重写它是不可行的,那么有一个解决方法:

Google App Script 似乎按照它们的创建顺序加载代码文件。首先是最旧的文件,然后是下一个,最后是最近创建的文件。这是未选中“按字母顺序排列文件”时在编辑器中显示的顺序。

因此,如果您按此顺序保存文件:

  • 代码.gs
  • 1_File.gs(取决于 0_File.gs)
  • 0_文件.gs

一个简单的解决方法是制作 1_File.gs 的副本,然后删除原始文件,从而有效地将其移动到列表的末尾。

  1. 单击 1_File.gs 旁边的三角形并选择“制作副本”
    • 代码.gs
    • 1_文件.gs
    • 0_文件.gs
    • 1_文件复制.gs
  2. 单击 1_File.gs 旁边的三角形并选择“删除”
    • 代码.gs
    • 0_文件.gs
    • 1_文件复制.gs
  3. 单击 1_File copy.gs 旁边的三角形并选择“重命名”,然后从末尾删除“副本”。
    • 代码.gs
    • 0_文件.gs
    • 1_文件.gs

现在 0_File.gs 在 1_File.gs 之前加载。

于 2018-01-03T02:40:51.570 回答
0

截至 2021 年 12 月,这对我有用。很可能,其他答案已经过时了。

您可以轻松解决此问题。当您查看 Web 编辑器的“文件”部分中的脚本时,您会看到它们有一个顺序。文件按照它们在那里出现的顺序进行评估。单击文件名右侧的三个点会弹出一个菜单,允许您向上或向下移动文件。

于 2021-12-06T07:48:07.703 回答
-1

Google Apps 脚本中没有这样的顺序。这完全取决于您在哪里声明这些对象以及如何调用您的函数。您能否解释一下如何以及何时调用 Logger.log() 代码。另外,你什么时候声明你的对象 objA 和 objB ?这些将帮助我们提供更好的答案

于 2012-10-02T16:19:27.280 回答
-2

这就是我将如何做到这一点...

主要的

function include(filename) {
  return ContentService.createTextOutput(filename);
}

function main() {
  include('Obj A');
  include('Obj B');
  Logger.log(ObjA.sayName + " : " + ObjB.sayName);
}

对象 A

var ObjA = new Object();
ObjA.sayName = " I'm A ";

对象 B

var ObjB = new Object();
ObjB.sayName = "[" + ObjA.sayName + "]";
于 2014-02-06T21:35:41.393 回答