ReferenceError:'e'未定义。
或者
TypeError:无法从未定义的*...*读取属性
(其中e
未定义)
可以将事件视为可选参数,并使用有更好的方法在JavaScript中处理可选函数参数吗?中的任何技术将默认值插入到触发函数中。但这会带来风险,即懒惰的程序员(如果是您,请举手!)会留下该代码,并产生意想不到的副作用。
肯定有更好的方法吧?
ReferenceError:'e'未定义。
或者
TypeError:无法从未定义的*...*读取属性
(其中e
未定义)
可以将事件视为可选参数,并使用有更好的方法在JavaScript中处理可选函数参数吗?中的任何技术将默认值插入到触发函数中。但这会带来风险,即懒惰的程序员(如果是您,请举手!)会留下该代码,并产生意想不到的副作用。
肯定有更好的方法吧?
您可以编写一个测试函数,向触发器函数传递模拟事件。以下是测试一个 onEdit()
触发器函数的示例。它会传递一个事件对象,其中包含“电子表格编辑事件”中描述的所有信息,请参见了解事件。
要使用它,请在目标 onEdit
函数中设置断点,选择函数 test_onEdit
,然后点击 Debug
。
/**
* Test function for onEdit. Passes an event object to simulate an edit to
* a cell in a spreadsheet.
*
* Check for updates: https://dev59.com/7mQo5IYBdhLWcg3wZelg#16089067
*
* See https://developers.google.com/apps-script/guides/triggers/events#google_sheets_events
*/
function test_onEdit() {
onEdit({
user : Session.getActiveUser().getEmail(),
source : SpreadsheetApp.getActiveSpreadsheet(),
range : SpreadsheetApp.getActiveSpreadsheet().getActiveCell(),
value : SpreadsheetApp.getActiveSpreadsheet().getActiveCell().getValue(),
authMode : "LIMITED"
});
}
如果您好奇,这是为了测试Google表格三个单元格条件格式的onEdit
函数而编写的。
下面是用于电子表格表单提交事件的测试函数。它通过读取表单提交数据来构建模拟事件。这最初是为如何修复onFormSubmit触发器中的TypeError错误?而编写的。
/**
* Test function for Spreadsheet Form Submit trigger functions.
* Loops through content of sheet, creating simulated Form Submit Events.
*
* Check for updates: https://dev59.com/7mQo5IYBdhLWcg3wZelg#16089067
*
* See https://developers.google.com/apps-script/guides/triggers/events#google_sheets_events
*/
function test_onFormSubmit() {
var dataRange = SpreadsheetApp.getActiveSheet().getDataRange();
var data = dataRange.getValues();
var headers = data[0];
// Start at row 1, skipping headers in row 0
for (var row=1; row < data.length; row++) {
var e = {};
e.values = data[row].filter(Boolean); // filter: https://dev59.com/yGIj5IYBdhLWcg3wx34x#19888749
e.range = dataRange.offset(row,0,1,data[0].length);
e.namedValues = {};
// Loop through headers to create namedValues object
// NOTE: all namedValues are arrays.
for (var col=0; col<headers.length; col++) {
e.namedValues[headers[col]] = [data[row][col]];
}
// Pass the simulated event to onFormSubmit
onFormSubmit(e);
}
}
在模拟事件时,请尽可能准确地匹配文档中记录的事件对象。
如果您希望验证文档,可以记录从触发函数接收到的事件。
Logger.log( JSON.stringify( e , null, 2 ) );
在电子表格表单提交事件中:
values
数组会跳过空白答案。使用filter(Boolean)
方法模拟此行为。*格式设置为“纯文本”的单元格将保留日期作为字符串,并且这不是一个好主意。
« /* {"namedValues":{"user name":["test name"],"a comment":["gxfgxdfhdgfhjfgjhfgjxfgj"],"Timestamp":["1/2/2014 22:17:24"]},"values":["1/2/2014 22:17:24","test name","gxfgxdfhdgfhjfgjhfgjxfgj"],"source":{},"range":{"rowStart":2,"rowEnd":2,"columnEnd":3,"columnStart":1}} */ »
括号在那里!!!所以它并不是很新...摘自:「Google Apps Script for Beginners [eBook].epub.」iBooks. - Serge insas无需像之前的答案建议的那样使用任何种类的模拟事件。
如问题所述,如果您直接在脚本编辑器中“运行”函数,则会抛出诸如
TypeError: 无法从未定义的对象读取属性 ...
这些不是真正的错误。这个错误只是因为您在没有事件的情况下运行了函数。如果您的函数表现不如预期,您需要找出实际的错误:
要测试触发器函数,请执行以下操作:
手动触发相应的事件:即,要测试onEdit
,请编辑工作表中的单元格;要测试onFormSubmit
,请提交虚拟表单响应;要测试doGet
,请将浏览器导航到已发布的webapp /exec
url。
如果有任何错误,则记录到stackdriver中。要查看这些日志,请执行以下操作:
在脚本编辑器中,单击左侧栏上的执行图标(旧版编辑器:查看 > 执行)。
或者,点击此处 > 点击您感兴趣的项目 > 单击左侧栏上的“执行”图标(第四个)
在执行页面中,您会找到执行列表。请确保清除顶部左侧的任何筛选器(如“Ran as:Me”),以显示所有执行项。单击您感兴趣的执行项,它将显示导致触发器失败的错误信息(以红色显示)。
注意:有时由于错误,日志无法显示。特别是对于由匿名用户运行的Web应用程序而言更为常见。在这种情况下,建议切换默认的Google Cloud项目到标准的Google Cloud项目,并直接使用“查看> Stackdriver日志记录”。有关详细信息,请参见此处。
console.log(/*您感兴趣的对象*/)
以查看该对象的详细信息。强烈建议您将要查找的对象转换为字符串:console.log(JSON.stringify(e))
,因为日志查看器具有某些特殊性质。添加console.log()
后,请重复从第1步开始进行调试,直到缩小问题范围。恭喜!您已成功找出了问题并跨过了第一个障碍。
2017更新:
使用Stackdriver Logging为Google应用脚本调试事件对象。在脚本编辑器的菜单栏中,转到:查看> Stackdriver日志记录
以查看或流式传输日志。
console.log()将写入DEBUG
级别的消息
onEdit()使用示例:
function onEdit (e) {
var debug_e = {
authMode: e.authMode,
range: e.range.getA1Notation(),
source: e.source.getId(),
user: e.user,
value: e.value,
oldValue: e. oldValue
}
console.log({message: 'onEdit() Event Object', eventObject: debug_e});
}
关于onFormSubmit()
的示例:
function onFormSubmit (e) {
var debug_e = {
authMode: e.authMode,
namedValues: e.namedValues,
range: e.range.getA1Notation(),
value: e.value
}
console.log({message: 'onFormSubmit() Event Object', eventObject: debug_e});
}
示例onChange():
function onChange (e) {
var debug_e = {
authMode: e.authMode,
changeType: changeType,
user: e.user
}
console.log({message: 'onChange() Event Object', eventObject: debug_e});
}
然后检查在Stackdriver UI中标记为message
字符串的日志,以查看输出。
/**
*
* like Logger.log %s in text is replaced by subsequent (stringified) elements in array A
* @param {string | object} text %s in text is replaced by elements of A[], if text is not a string, it is stringified and A is ignored
* @param {object[]} A array of objects to insert in text, replaces %s
* @returns {string} text with objects from A inserted
*/
function Stringify(text, A) {
var i = 0 ;
return (typeof text == 'string') ?
text.replace(
/%s/g,
function(m) {
if( i >= A.length) return m ;
var a = A[i++] ;
return (typeof a == 'string') ? a : JSON.stringify(a) ;
} )
: (typeof text == 'object') ? JSON.stringify(text) : text ;
}
/* use Logger (or console) to display text and variables. */
function T(text) {
Logger.log.apply(Logger, arguments) ;
var Content = Stringify( text, Array.prototype.slice.call(arguments,1) ) ;
return Content ;
}
/**** EXAMPLE OF USE ***/
function onSubmitForm(e) {
T("responses:\n%s" , e.response.getItemResponses().map(r => r.getResponse()) ;
}