You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

继承Array重写filter方法异常:构造函数被传入[0]

继承Array时filter方法触发构造函数传入[0]的根本原因及解决办法

根本原因

内置Array.prototype.filter方法在生成结果数组时,会使用原数组的构造函数来创建新实例。当你调用Array.prototype.filter.call(this, predicate)时,this是MyArray的实例,所以filter内部会调用new MyArray(0)——这里的0是filter用来初始化新数组长度的默认参数。

你的MyArray构造函数对单参数的处理逻辑完全违背了内置Array的设计:内置Array在传入单个数字时是指定数组长度(比如new Array(3)生成长度为3的空数组),但你却把这个长度参数当成了元素,重置length为0后再push进去,导致原本应该是空数组的结果变成了[0]。

执行流程拆解

  1. 调用myArray.filter(num => num === "nonsense")时,filter遍历原数组后发现没有符合条件的元素,需要创建一个长度为0的新数组。
  2. 由于myArray是MyArray实例,filter会调用new MyArray(0)来生成结果。
  3. 你的构造函数检测到nums.length === 1,执行this.length = 0并push传入的0,最终得到[0]而非预期的空数组。
  4. [...this].filter(predicate)能解决问题,是因为[...this]把MyArray实例转成了普通Array,filter返回的是普通空数组,不会触发MyArray的构造函数,但会产生额外的数组拷贝。

无拷贝的正确解决方式

要让filter返回正确的MyArray实例,需要让构造函数兼容内置Array的两种调用逻辑:单个数字参数表示数组长度,多个参数表示初始化元素。修改后的代码如下:

class MyArray extends Array {
  constructor(...nums) {
    // 兼容内置Array的两种构造逻辑
    if (nums.length === 1 && typeof nums[0] === 'number') {
      super(nums[0]);
    } else {
      super(...nums);
    }
    this.tmpStore = {}; // 保留你的自定义属性
  }
  
  filter(predicate) {
    // 直接调用super.filter即可,内置逻辑会正确创建MyArray实例
    return super.filter(predicate);
  }
}

修改后,当filter调用new MyArray(0)时,构造函数会按长度初始化出空数组,完全符合预期,且没有额外的数组拷贝开销。

内容的提问来源于stack exchange,提问作者crazyones110

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 13:20:21