Symbol.species是否起效,关键看子类实例调用map等内置方法后返回值的constructor是否为期望构造器;它只影响返回新对象的方法(如map、filter、then),不改变继承或new行为,须通过static get [Symbol.species]()定义。
识别 Symbol.species 是否在起作用,关键看“子类实例调用内置方法后,返回值的构造器是不是你期望的那个”。它不改变类继承关系,也不影响你手动 new,只悄悄干预 map、filter、slice、then 这类会返回新对象的内置方法。
最直接的方式:调用方法后检查返回值的 constructor 和 instanceof 结果。
arr.map(x => x) 返回的对象,arr.constructor === Array?还是 === MyArray?result instanceof MyArray 是 true 还是 false?result.constructor 指向父类(如 Array),且 instanceof MyArray 为 false,说明 Symbol.species 起效了(且返回的是父类)。Symbol.species 必须通过静态访问器属性定义,不能写在实例上,也不能用箭头函数。
static get [Symbol.species]() { return this; } 或 return Array;
[Symbol.species]: () => Array(箭头函数无 this)、this[Symbol.species] = ...(实例属性无效)、get [Symbol.species]() { ... }(非 static)MyArray[Symbol.species] 应该是一个函数;typeof MyArray[Symbol.species] 应为 "function"。如果子类添加了专属方法(比如 MyArray.prototype.getFirst),而 map 后的结果无法调用它,大概率是因为返回的是原生 Array。
const a = new MyArray(1,2); const b = a.map(x => x); b.getFirst(); // TypeError → 说明 b 是 Array 实例,Symbol.species 已生效(或未设置,回退到默认 Array)b.getFirst() 正常执行,说明 map 返回了 MyArray,此时要确认是否显式设置了 [Symbol.species]() { return this; }。不是所有方法都读取 Symbol.species。只限明确规范中指定使用它的内置方法:
map、filter、slice、concat、flat、flatMap
then、catch、finally
replace(生成新正则时)、split(某些实现)filter(非标准,但部分 polyfill 或引擎扩展可能支持)map 方法不会自动读取它——必须手动实现逻辑: this.constructor[Symbol.species]。