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

子类继承Array后map调用自身构造器,如何改为调用Array构造器?

问题与解决方案

问题详情

当对继承自Array的ConsoleText类实例text调用map()方法时,会触发ConsoleText(text.length)构造器调用(示例中最后一行构造器输入为2)。如何修改才能让text.map()调用Array构造器?这是否属于继承的特性?

示例代码

'use strict'

let initializingText = true;

class ConsoleText extends Array {
  constructor(strings) {
    console.log('构造器输入:', strings);
    if (initializingText) {
      super(...strings);
    } else {
      super('item1', 'item2', 'item3', 'item4', 'item5');
    }
  }
}

let text = new ConsoleText(['a', 'b']);   // 构造器输入:(2) ['a', 'b']

console.log('text:', text);   // text: ConsoleText(2) ['a', 'b']

initializingText = false;   // 切换以避免解构数字时出错

console.log(text.map(() => 'q'));   // 构造器输入:2
                                    // ConsoleText(5) ['q', 'q', 'item3', 'item4', 'item5']

解答

这是继承的特性吗?

是的,这属于JavaScript数组子类的固有特性。数组的迭代方法(如map、filter、slice等)在创建新数组时,默认会使用当前实例的constructor构造新对象,也就是示例中的ConsoleText构造器。所以调用map时,会传入新数组的长度作为参数,触发ConsoleText的构造函数。

修改方法

通过重写类的Symbol.species getter,指定迭代方法创建新数组时使用Array构造器而非子类ConsoleText。Symbol.species是内置符号,用于定义派生对象的构造函数。

修改后的代码如下:

'use strict'

let initializingText = true;

class ConsoleText extends Array {
  constructor(strings) {
    console.log('构造器输入:', strings);
    if (initializingText) {
      super(...strings);
    } else {
      super('item1', 'item2', 'item3', 'item4', 'item5');
    }
  }

  // 重写Symbol.species,指定使用Array构造器
  static get [Symbol.species]() {
    return Array;
  }
}

let text = new ConsoleText(['a', 'b']);   // 构造器输入:(2) ['a', 'b']

console.log('text:', text);   // text: ConsoleText(2) ['a', 'b']

initializingText = false;   // 切换以避免解构数字时出错

console.log(text.map(() => 'q'));   // 不再触发ConsoleText构造器
                                    // 输出:Array(2) ['q', 'q']

修改后,map方法会用Array构造器创建新数组,不会再触发ConsoleText的构造函数调用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 13:45:30