JavaScript中同一类无法访问私有字段?TypedMap子类报错排查
错误原因分析
你遇到的报错核心有两个关键诱因:
1. 私有字段声明位置错误
JavaScript的私有字段(#前缀)必须在类的顶层作用域声明,不能放在构造函数内部。如果你的代码是在构造函数里写#keyType和#valueType,那这些只是构造函数的局部私有变量,不属于实例的私有字段。当重写的set方法试图访问this.#keyType时,因为类本身没有声明这个私有字段,就会抛出“Cannot read private member #keyType from an object whose class did not declare it”的错误。
2. 构造函数执行顺序冲突
即使你正确声明了私有字段,若先调用super(entries)再赋值#keyType和#valueType,super(entries)会触发Map构造函数遍历entries并调用子类的set方法——此时#keyType还未被初始化,不仅类型校验会失效,也可能引发关联错误。
正确的TypedMap实现
class TypedMap extends Map { // 必须在类顶层声明私有字段 #keyType; #valueType; constructor(entries = [], keyType, valueType) { // 先调用super()初始化父类,不传entries避免提前触发set super(); // 初始化私有字段(此时可正常访问this) this.#keyType = keyType; this.#valueType = valueType; // 手动验证并添加所有entries for (const [key, value] of entries) { this.set(key, value); } } set(key, value) { // 校验键类型 if (!(key instanceof this.#keyType)) { throw new TypeError(`无效键类型:预期${this.#keyType.name},实际${typeof key}`); } // 校验值类型 if (!(value instanceof this.#valueType)) { throw new TypeError(`无效值类型:预期${this.#valueType.name},实际${typeof value}`); } // 调用父类的set方法完成存储 return super.set(key, value); } test() { console.log(`键类型:${this.#keyType.name},值类型:${this.#valueType.name}`); } }
使用示例
// 实例化键为Number、值为String的TypedMap const numStrMap = new TypedMap([[1, "one"], [2, "two"]], Number, String); numStrMap.test(); // 输出:键类型:Number,值类型:String // 正常添加符合类型的键值对 numStrMap.set(3, "three"); // 尝试添加错误类型会抛出错误 numStrMap.set("3", "three"); // TypeError: 无效键类型:预期Number,实际string
内容的提问来源于stack exchange,提问作者Othmane
相关产品推荐
相关产品推荐

