es6 class 无法直接继承 array、map、set 并保持其内置行为;array 可通过 reflect.construct 绕过限制,而 map/set 应采用组合或 proxy 封装方案。

ES6 的 class 语法本身不支持直接继承内置可扩展对象(如 Array、Map、Set)并保持其内置行为,因为这些类的构造函数在内部使用了特殊的 [[IsArray]] 或内部槽位机制,而普通子类无法正确继承这些底层特性。但有几种可行方案,关键在于绕过默认的 new.target 行为或使用代理/封装。
用 extends + constructor 中手动调用父类构造器(仅对 Array 有限有效)
对于 Array,可以借助 Reflect.construct 或返回新数组实例的方式“模拟”继承,但要注意:子类实例不会被 Array.isArray() 认为是数组,除非用 Symbol.species 配合 Array.prototype 方法重定向。
- 不能直接写
class MyArray extends Array { constructor(...args) { super(...args); } }—— 这样创建的实例虽有数组方法,但Array.isArray(new MyArray())返回false - 正确做法是:在构造器中用
Reflect.construct(Array, args, new.target),确保 [[IsArray]] 内部标志被设置 - 示例:
class MyArray extends Array { constructor(...args) { return Reflect.construct(Array, args, new.target); } } const arr = new MyArray(1, 2, 3); console.log(Array.isArray(arr)); // true console.log(arr.map(x => x * 2)); // [2, 4, 6]
Map 和 Set 不支持标准 extends 继承
Map 和 Set 的构造器不允许通过 super() 正常调用,且 Reflect.construct(Map, [], new.target) 在多数引擎中会抛错(V8 早期版本不支持,新版部分支持但行为不稳定)。官方明确说明:它们不可被子类化。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 尝试
class MyMap extends Map {}会导致TypeError: Illegal constructor - 根本原因是
Map构造器检查this是否由其自身或兼容的内置构造器创建,子类实例不满足该条件 - 所以不要强行
extends Map,应改用组合(composition)方式
推荐方案:用组合代替继承(最可靠)
把原生对象作为私有字段保存,再暴露同名方法,既保持行为一致性,又避免继承陷阱。
- 例如封装
Map:class MyMap { #map = new Map(); constructor(iterable) { if (iterable) { for (const [k, v] of iterable) this.#map.set(k, v); } } set(key, value) { return this.#map.set(key, value); } get(key) { return this.#map.get(key); } has(key) { return this.#map.has(key); } size() { return this.#map.size; } // 其他方法依此类推…… } - 优点:完全可控、无兼容性风险、类型检查友好(TypeScript 可精确标注)
- 缺点:需手动代理所有方法,但可用
Object.getOwnPropertyNames(Map.prototype)动态挂载(注意不可枚举方法如@@iterator)
高级技巧:Proxy 封装(适合只读或拦截场景)
若只需增强行为(如日志、验证),可用 Proxy 包裹原生实例,无需继承。
- 示例:带访问日志的 Map
function createLoggedMap() { const map = new Map(); return new Proxy(map, { get(target, prop) { console.log(`Accessing ${String(prop)}`); return target[prop]; }, set(target, key, value) { console.log(`Setting ${key} = ${value}`); target.set(key, value); return true; } }); } - 适合装饰模式,不适合需要 instanceof 检查或深度集成的场景
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










