【发布时间】:2018-11-01 17:22:07
【问题描述】:
TL;DR - 我的类声明中的 super 关键字有时(但不总是)未定义。如何/为什么?
我有以下扩展 Array 的类声明,用于来自 API 的搜索结果数据:
class SearchResult extends Array {
constructor(resultArray) {
super(...resultArray);
}
static createFromApiData(apiData) {
const resultArray = apiData.filter(...).map(...);
return new SearchResult(resultArray);
}
...otherMethods
}
在我的应用中,它最初是在接收到 API 的响应时立即调用的,如下所示:
apiCall().then((res) => {
const searchResults = SearchResult.createFromApiData(res.data);
});
使用这个静态方法创建一个新的SearchResult 实例可以正常工作,返回我想要的。
但是,稍后在我的应用程序中,我需要再次创建一个 SearchResult 实例,这次不需要 API 调用,因为我已经将 resultArray 数据存储在数据库中。因此,我第二次尝试使用new 关键字创建SearchResult 的实例,如下所示:
const searchResults = new SearchResult(resultArray);
这一次,使用 new 关键字创建实例失败并抛出以下错误:
TypeError: undefined is not a function at new SearchResult
我知道undefined 在这种情况下指的是super 关键字,但我不明白为什么会这样?在这两种情况下,实例创建行为如何变化?我该如何解决?
更新
我进一步调查并发现了以下内容。我最初的问题是因为我将自定义 SearchResult 类实例保存到数据库 (dynamodb)。虽然SearchResult 扩展了数组,ddb 把它保存为基本对象,所以从数据库中检索数据时它是以基本对象的形式出现的,而不是数组形式。当我试图在 super 函数内传播对象时,这会引发错误。
我通过在将类实例保存到 ddb 时将其分布在一个新数组中解决了这个问题:
db.save([...searchResults]);
这在数据库调用后返回了一个数组,并且可以在 super 调用中成功传播。
但是,这导致了一个新问题。在创建新的SearchResult 实例后,我立即对其调用以下自定义方法:
nextItem() {
this.splice(0, 1);
return this[0];
}
然后此方法再次调用super 以访问Array 上的splice 方法。但是,这再次失败,抛出与以前相同的错误:
{
"errorMessage": "undefined is not a function",
"errorType": "TypeError",
"stackTrace": [
"new SearchResult",
"SearchResult.splice",
"SearchResult.nextRecipe"
}
这又是指super 内部的展开操作。这一次 super 被传递数字 1 作为它的唯一参数。 1 来自哪里,我该如何解决?
更新 2
在将类方法更新为shift 而不是splice 后,该方法现在可以正常工作而不会出现错误。我的问题现在得到了有效解决,但是我仍然希望了解super 被1 调用的问题与splice 有关。为什么这两个数组方法在这种情况下会有不同的表现。
nextItem() {
return this.shift();
}
【问题讨论】:
-
你确定这个错误真的是
super()调用引起的吗?还是只是“在那一行”?
标签: javascript class new-operator extends super