【问题标题】:filter() is buggy, when I extend the Array class当我扩展 Array 类时,filter() 是错误的
【发布时间】:2021-08-12 23:50:32
【问题描述】:

我认为在 javascript 中扩展数组会很有用,可以通过一些自定义方法和业务逻辑来增强它们。 到目前为止,它运行良好,直到我尝试过滤我的实例。

似乎数组filter 方法用一个参数调用我的构造函数(0,如果没有找到)并返回一个新实例。不是我所期望的。

class MyArray extends Array {
  constructor(x, y, z) {
    super(x, y, z);
    // do custom stuff
  }
}

let numbers = new MyArray(1, 2, 3);
console.log(numbers.filter((v) => v === 0));

不过,如果我将一些参数传递并传播到一个变量中,一切都会正常进行。

从技术上讲,我认为两者之间没有区别,我不明白!

class MyArray extends Array {
  constructor(x, ...args) {
    super(x, ...args);;
    // do custom stuff
  }
}

let numbers = new MyArray(1, 2, 3);
console.log(numbers.filter((v) => v === 0));
  1. 为什么第一种方法会遇到这个问题?
  2. 为什么第二种方法没有遇到这种情况?

(扩展数组或其他核心 js 类是不好的做法吗?)

【问题讨论】:

  • 这能回答你的问题吗? Ways to extend Array object in javascript
  • 可以使用一个参数指定所需长度或多个参数来指定初始数组元素来调用数组构造函数。 filter() 正在使用第一种方法创建一个空数组,然后将其推入。
  • 我强烈建议不要在 Javascript 中扩展内置对象。您的代码库中的任何其他库都可能因为您劫持默认对象而中断。我还建议使用更适合 Javascript 的纯函数,而不是尝试扩展类。不要试图让数组更智能,尝试在使用数组作为实现细节的函数中编写业务逻辑。
  • @AndyRay OP 是 Array 的子类化,这很好,他们没有在修补原型。
  • 或者,如果您希望filter 不构造MyArray,您可以将@@species 设置为Array

标签: javascript arrays inheritance


【解决方案1】:

Array 构造函数的行为取决于它接收的参数的数量和类型。

如果它接收到包含整数的单个参数,则此参数是数组的初始大小。它返回一个该大小的数组,其中元素未初始化。

在其他情况下,参数是数组的初始元素。

所以当您调用super(x, y, z) 时,您使用的是第二种格式,它会创建一个最初包含值x, y, z 的数组。

filter() 使用第一种格式调用您的构造函数,因此x 是它请求的数组的大小(如您所说的0)。但是你的构造函数有额外的参数yz,所以它们被设置为undefined。所以你调用super(0, undefined, undefined),它正在创建一个数组[0, undefined, undefined]

您的第二个构造函数几乎是正确的,但真正的 Array 构造函数可以不带参数调用,返回一个空数组。如果以这种方式调用您的构造函数,它将调用super(undefined),创建一个包含undefined 的单个元素的数组。定义构造函数的正确方法是使用单个展开参数。这不会对filter() 产生影响,但可能会影响其他代码。

class MyArray extends Array {
  constructor(...args) {
    super(...args);;
    // do custom stuff
  }
}

let numbers = new MyArray(1, 2, 3);
console.log(numbers.filter((v) => v === 0));

【讨论】:

  • 感谢您抽出宝贵时间进行解释!它有很大帮助,我将能够通过此解决方案解决我的问题!
猜你喜欢
  • 2014-06-20
  • 1970-01-01
  • 2019-08-12
  • 2011-04-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多