Javascript Google脚本中的全局变量(电子表格)
我一直在尝试在GoogleApps脚本(在电子表格中)中使用一些函数来修改全局变量,但我似乎无法理解 基本上,我想声明一个变量(在本例中为“globalTestVar”),并且每次两个函数(GlobalArtestFunctionOne和two)中的一个启动时,该变量都应该递增一 问题是,每次按下按钮时都会再次声明变量,即使if(typeof(globalTestVar)==“undefined”)-语句应该处理这个问题 我已经习惯了Objective C和Java,我可以在开始时声明变量,并在代码中的任何地方修改这些变量 如果这是一个基本的问题,我很抱歉,但我已经在谷歌上搜索了好几个小时,我就是无法让它工作 代码如下:Javascript Google脚本中的全局变量(电子表格),javascript,variables,google-apps-script,global,Javascript,Variables,Google Apps Script,Global,我一直在尝试在GoogleApps脚本(在电子表格中)中使用一些函数来修改全局变量,但我似乎无法理解 基本上,我想声明一个变量(在本例中为“globalTestVar”),并且每次两个函数(GlobalArtestFunctionOne和two)中的一个启动时,该变量都应该递增一 问题是,每次按下按钮时都会再次声明变量,即使if(typeof(globalTestVar)==“undefined”)-语句应该处理这个问题 我已经习惯了Objective C和Java,我可以在开始时声明变量,并在
logstuff("outside");
function logstuff(logInput){
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet1');
var lastRow = sheet.getLastRow() + 1;
sheet.getRange("A"+lastRow).setValue(logInput);
return;
}
if (typeof(globalTestVar) == 'undefined') {
logstuff('declaring global variable');
globalTestVar = 0;
} else {
logstuff('global variable has been declared');
}
function globalVarTestUIFunction() {
var app = UiApp.createApplication().setTitle('Test UI');
var doc = SpreadsheetApp.getActive();
var formPanel = app.createVerticalPanel();
var buttonF1 = app.createButton('F1');
var buttonbuttonF1ClickHandler = app.createServerClickHandler("globalVarTestFunctionOne");
buttonF1.addClickHandler(buttonbuttonF1ClickHandler);
buttonbuttonF1ClickHandler.addCallbackElement(formPanel);
var buttonF2 = app.createButton('F2');
var buttonbuttonF2ClickHandler = app.createServerClickHandler("globalVarTestFunctionTwo");
buttonF2.addClickHandler(buttonbuttonF2ClickHandler);
buttonbuttonF2ClickHandler.addCallbackElement(formPanel);
app.add(formPanel);
formPanel.add(buttonF1);
formPanel.add(buttonF2);
doc.show(app);
return app;
}
function globalVarTestFunctionOne() {
logstuff('globalVarTestFunctionOne');
globalTestVar++;
logstuff('Value of globalTestVar: ' + globalTestVar);
}
function globalVarTestFunctionTwo() {
logstuff('globalVarTestFunctionTwo');
globalTestVar++;
logstuff('Value of globalTestVar: ' + globalTestVar);
}
输出:
- 外部3
- 声明全局变量
- 外部3
- 声明全局变量
- 全动脉功能酮
- globalTestVar的值:1
- 外部3
- 声明全局变量
- 全球动脉功能二
- globalTestVar的值:1
谢谢大家! 您不会喜欢这样:GAS中的全局变量是静态的-您不能更新它们并期望它们保留其值。一、 同样,谷歌搜索了几个小时 您可以使用
CacheService
或ScriptDB
作为此类问题的可能存储CacheService
快速且易于使用,但受到限制,因为缓存最终将过期。我还没有尝试ScriptDBPropertiesService->Properties
目前(2015年),我认为应该使用类和返回类型
关于全球范围
据我所知,每次对脚本函数的新调用(时间触发器、用户单击菜单项、按下按钮等)都将导致对脚本进行新的完整解析,而不会记忆以前的执行情况,除非它们以某种方式被持久化(例如,在电子表格范围内或使用
属性
).尽管CacheService可以工作,但它的最长使用寿命为6小时。
这可以通过使用PropertiesService来解决,如@consideRatio所述
示例包装器可能是(将变量注入全局上下文)
注册Globals.init后,变量可以像普通变量一样使用。不过,这适用于原语,因为复杂对象不支持观察程序,所以必须在脚本端或显式刷新它们
/* In case you need to start over */
function restart_simulations() {
Globals.reset('counter');
Globals.reset('state');
test_run();
}
function test_run() {
/* After running init once, you can use global var as simple variable */
Globals.init('counter', 1); // Required to use "counter" var directly, as simple variable
/* Complex objects are also accepted */
Globals.init('state', { logined: false, items: [] });
/* Using primitives is simple */
Logger.log('Counter was ' + counter);
counter = counter + 1;
Logger.log('Counter is now ' + counter);
/* Let's modify complex object */
Logger.log('State was ' + JSON.stringify(state));
state.items.push(state.logined ? 'foo' : 'bar');
state.logined = ! state.logined;
Logger.log('State is now ' + JSON.stringify(state));
/* Unfortunately, watchers aren't supported. Non-primitives have to be flushed */
/* Either explicitly */
//Globals.save('state');
/* Or all-at-once, e.g. on script end */
Globals.flush();
}
以下是在不同的3次跑步中保留的内容
First run:
[20-10-29 06:13:17:463 EET] Counter was 1
[20-10-29 06:13:17:518 EET] Counter is now 2
[20-10-29 06:13:17:520 EET] State was {"logined":false,"items":[]}
[20-10-29 06:13:17:523 EET] State is now {"logined":true,"items":["bar"]}
Second run:
[20-10-29 06:13:43:162 EET] Counter was 2
[20-10-29 06:13:43:215 EET] Counter is now 3
[20-10-29 06:13:43:217 EET] State was {"logined":true,"items":["bar"]}
[20-10-29 06:13:43:218 EET] State is now {"logined":false,"items":["bar","foo"]}
Third run:
[20-10-29 06:14:22:817 EET] Counter was 3
[20-10-29 06:14:22:951 EET] Counter is now 4
[20-10-29 06:14:22:953 EET] State was {"logined":false,"items":["bar","foo"]}
[20-10-29 06:14:22:956 EET] State is now {"logined":true,"items":["bar","foo","bar"]}
您可以在这里查看工作示例
好吧,这太令人不安了。必须有一种使用某种全局变量的方法。我考虑了一种变通方法,使用“变量”表来保存/修改和获取全局变量。但这不是很优雅,也不是很有效。我使用了
CacheService
来做我需要的事情,但那是短期存储以提高性能。您可能会发现ScriptDB
更好,但我没有尝试过。是的,cacheService对字符串和数字很有效,但是可以使用cacheService存储数组吗?否-您不能在缓存中存储数组,更糟糕的是:JSON.stringify()
似乎不会返回JSON字符串,也不会报告错误。不过,您可以将数组存储在ScriptDB中。这是否比将它们存储为表中的范围更好取决于您对它们所做的操作。全局变量不是静态的,它们是全局的,指的是它们的作用域。在执行上下文中,全局变量可用于所有代码块。当您按下客户端脚本(UiApp、HtmlService)中的按钮时,将创建一个新的服务器端上下文以运行相应的处理程序,并且该新上下文具有一组唯一的“全局”变量。严格地说,您的变量没有被“重新声明”,与“未定义”的比较只意味着它没有在此上下文中赋值。
First run:
[20-10-29 06:13:17:463 EET] Counter was 1
[20-10-29 06:13:17:518 EET] Counter is now 2
[20-10-29 06:13:17:520 EET] State was {"logined":false,"items":[]}
[20-10-29 06:13:17:523 EET] State is now {"logined":true,"items":["bar"]}
Second run:
[20-10-29 06:13:43:162 EET] Counter was 2
[20-10-29 06:13:43:215 EET] Counter is now 3
[20-10-29 06:13:43:217 EET] State was {"logined":true,"items":["bar"]}
[20-10-29 06:13:43:218 EET] State is now {"logined":false,"items":["bar","foo"]}
Third run:
[20-10-29 06:14:22:817 EET] Counter was 3
[20-10-29 06:14:22:951 EET] Counter is now 4
[20-10-29 06:14:22:953 EET] State was {"logined":false,"items":["bar","foo"]}
[20-10-29 06:14:22:956 EET] State is now {"logined":true,"items":["bar","foo","bar"]}