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
数据存储在数据库中。因此,第二次尝试使用SearchResult
关键字创建new
的实例,如下所示:
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
以访问splice
上的Array
方法。但是,这再次引发与以前相同的错误:
{
"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();
}
答案 0 :(得分:1)
我知道在这种情况下undefined指的是super关键字,但我不明白为什么是这种情况?
可能不是。 super
指向该类的内部不可更改的[[HomeObject]]属性,该属性在声明该类时设置,您不能修改它,只能重写该类本身,例如:
SearchResult = function() { undefined(); }
但是我想你不会那样做。
但是错误从哪里来?
那一行发生了两件事:
super(...resultArray);
一个是super()
调用,另一个是resultArray
的扩展,这将创建并使用resultArray
的迭代器,该迭代器几乎不等于:
resultArray[Symbol.iterator]()
,如果迭代器不存在(因为您不小心将非数组传递给了构造函数),它将失败,表示无法调用该迭代器:
var resultArray = {};
resultArray[Symbol.iterator]()
// equals:
undefined()