class 声明中未定义超级方法

super method undefined in class declaration

TL;DR - 我的 class 声明中的 super 关键字有时(但不总是)未定义。 How/why?

我有以下 class 扩展 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 class 实例保存到数据库 (dynamodb)。尽管 SearchResult 扩展数组,ddb 将其保存为基本对象,因此在从数据库中检索数据时,它以基本对象形式出现,而不是数组形式。当我试图在 super 函数内传播对象时,这会引发错误。

我通过将 class 实例保存到 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

在将 class 方法更新给我们 shift 而不是 splice 之后,该方法现在可以正常工作,没有错误。我的问题现在已得到有效解决,但我仍然希望了解 1 调用 super 的问题与 splice 的关系。为什么这两个数组方法在这种情况下表现不同。

nextItem() {
  return this.shift();
}

I know undefined in this context is referring to the super keyword but I can not understand why this is the case?

可能不会。 super 指的是 class 的内部不可更改的 [[HomeObject]] 属性,它在声明 class 时设置,你不能修改它,你可以只重写 class 本身,例如:

 SearchResult = function() { undefined(); }

但我猜你不会那样做。

但是错误从何而来?

那一行中发生了两件事:

 super(...resultArray);

一个是 super() 调用,另一个是 resultArray 的传播,它将创建并使用 resultArray 的迭代器,它几乎等于:

 resultArray[Symbol.iterator]()

如果迭代器不存在(因为你不小心传递了一个非数组给构造函数)它失败了,说迭代器不能被调用:

 var resultArray = {};

 resultArray[Symbol.iterator]()
 // equals:
 undefined()