如何获取对象类型
How to get the object type
在我的Google Apps脚本应用程序中,我看到以下错误:
脚本已完成,但返回值不是受支持的返回类型
如何找出要返回的值的类型?我试过了:
typeof(obj)
但我被告知的只是一个对象。
仅当缓存为空且从电子表格加载数据时,才会发生此错误。 例如,用户点击页面,获取错误,刷新现在加载页面,因为缓存是在第一次点击时填充的。现在用户可以继续使用该页面,直到缓存失效,然后下一次点击将再次导致此错误。
在我阅读并遵循此文档后,此错误今天开始发生。以前我的脚本在模板中加载数据,现在我重构为使用以下异步加载:
google.script.run
我查看了页面中发生的事情,了解为什么从缓存中读取时它有效,我唯一能看到的不同之处在于缓存中的数据是从 JSON 字符串解析的。当缓存为空时,我必须将对象字符串化才能保存到缓存中,因此我不会返回原始对象,而是解析我刚刚创建的字符串并返回该字符串,现在没有错误。
我也不确定错误来自哪里,是应用程序脚本还是 Caja?
解析 JSON 字符串以返回也不是理想的解决方案,这种字符串化/解析对我的原始对象做了什么来消除错误?
当我使用内置调试器检查对象时(在字符串化/解析过程之前和之后),值和类型似乎都与我所能检查
的相同。这是应用程序脚本中的错误吗?我做错了什么吗?消除此错误的最佳解决方案是什么?
我们可以扩展 JavaScript 对象,让它们告诉我们它们的对象类型,如如何在 JavaScript 中获取对象类型的名称?。但是,这不适用于Google Apps Script对象。
这是我整理的一个技巧,似乎适用于 GAS 对象。我没有尝试过每一个,但许多主要对象确实有效。
function getObjType(obj) {
var type = typeof(obj);
if (type === "object") {
try {
// Try a dummy method, catch the error
type = obj.getObjTypeXYZZY();
} catch (error) {
// Should be a TypeError - parse the object type from error message
type = error.message.split(" object ")[1].replace('.','');
}
}
return type;
}
下面是一个测试例程:
function test_getObjType() {
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
Logger.log("Spreadsheet: " + getObjType(spreadsheet));
var sheet = spreadsheet.getActiveSheet();
Logger.log("Sheet: " + getObjType(sheet));
var range = sheet.getActiveCell();
Logger.log("Range: " + getObjType(range));
var string = "Hello";
Logger.log("String: " + getObjType(string));
};
结果是:
[13-12-18 23:23:47:379 EST] Spreadsheet: Spreadsheet
[13-12-18 23:23:47:609 EST] Sheet: Sheet
[13-12-18 23:23:47:626 EST] Range: Range
[13-12-18 23:23:47:626 EST] String: string
我知道这是一个非常古老的帖子,但想让每个发现自己在谷歌推荐下的人都知道该解决方案不再有效。
我正在努力解决同样的问题,并尝试了建议的解决方案。看起来谷歌(再次)决定在不告诉任何人或更新文档的情况下更改其产品的功能。
错误消息不再包含对象类型,因此不是得到"TypeError:无法在对象中找到函数foobar",而是得到"TypeError:在对象中找不到函数foobar<在此处插入toString()的输出>"。
错误消息很可能总是使用 toString() 方法,并且由于 Google 从 toString() 方法中删除了对象类型,他们也破坏了这种获取对象类型的方式。
我只需要找出对象是数组还是字符串,并找到了一个技巧来解决这个问题。
function getObjType(obj) {
// If the object is an array, this will return the stored value,
// if the object is a string, this will return only one letter of the string
var type = obj[0];
if (type.length == 1) {
return 'string';
}
try {
type = obj.foobar();
} catch (error) {
// TypeError no longer contains object type, just return 'array'
Logger.log(error);
return 'array';
}
}
由于最高答案不再有效,我为自己的用例提出了一个黑客解决方案,后来发现Google内置了查找类型的功能。
为了举例说明上下文,如果您要遍历 Google 文档中的段落,并想知道该段落代表的是文本还是图像,则可以执行以下操作:
const childType = paragraph.getChild(0).getType();
if (childType == DocumentApp.ElementType.TEXT) {
// ...
}
else if (childType == DocumentApp.ElementType.INLINE_IMAGE) {
// ...
}
有关详细信息,请参阅文档。
我掉进了整个兔子洞,正准备编写一个"猜测类型"函数时,我想起问题始于 Logger 控制台刚刚吐出对象的"类型"名称,而不是带有成员的对象视图。事实证明,脚本类型的默认toString()
行为是返回其隐式类型名称:
const filter = range.createFilter();
Logger.log(filter.toString() == "Filter"); // true
Logger.log(filter + "" == "Filter"); // true
Logger.log(filter == "Filter"); // true
因此,只需将其与隐式类型名称进行比较即可检查脚本类型。我还不知道是否有具有不同toString()
行为的类型,所以如果幕后存在差异,也许使用类似 object + ""
的东西更健壮(?
这是我在Google Apps Script中获取对象类型的帮助程序函数:
/**
* Returns the object type.
*
* @param {*} obj
* @returns {string}
*/
function getObjectType(obj) {
let type = typeof obj;
if (type === 'object') {
if (Array.isArray(obj)) {
type = 'Array';
} else if (obj === null) {
type = 'null';
} else if (Object.prototype.toString.call(obj.getA1Notation) === '[object Function]') {
// JSDoc usage: @param {SpreadsheetApp.Range}
type = 'Range';
} else if (Object.prototype.toString.call(obj.getActiveCell) === '[object Function]') {
// JSDoc usage: @param {SpreadsheetApp.Sheet}
type = 'Sheet';
} else if (Object.prototype.toString.call(obj) === '[object Object]') {
// Some other object (this block should come last)
type = 'Object';
}
}
// Note that NaN (Not a Number) returns type `number`
return type;
}
随意使用它并根据您的需求扩展它以支持其他电子表格应用程序类。如果确实扩展了它,请尝试选择该类唯一的方法。
- 只能存储一种类型的对象的数组
- Mongoose TypeError:实例化模式类型的对象时,对象不是函数
- 为什么Javascript程序员更喜欢在代码中重复字符串作为常量,而不是使用枚举类型的对象
- 类型错误:对象 #<对象> 没有方法“身份验证”
- 未捕获的类型错误:对象#<节点列表>没有方法'addEventListener'
- 什么类型的对象/属性是原型getter和setter
- 未捕获的类型错误:对象没有方法'sortContents'
- 未捕获的类型错误:对象#<对象>没有方法'绑定'-脊梁骨
- 未捕获的类型错误:对象#<HTMLDivElement>没有方法'偏移'
- 使用鸭子类型的对象键入字符串文字
- 未捕获的类型错误:对象#<HTML对象元素>没有方法'重新绘制工作流'
- 未捕获的类型错误:对象#<对象>没有方法'substr'带标签的标记
- 类型错误:对象 #
没有方法“发送” - 未捕获的类型错误:对象 #<对象> 没有方法“超级鱼”
- 修复Javascript错误:未捕获的类型错误:对象[对象对象]没有“可调整大小”的方法
- 根据属性名称和类型对对象进行分组
- 主干.js未捕获的类型错误:对象 [对象数组] 没有方法“on”
- 类型错误: 对象函数...没有方法“打开”
- 未捕获的类型错误:对象 #<对象> 没有方法“newsticker”
- 未捕获的类型错误:对象 #
没有 onkeydown 方法