如何在JavaScript(Apps Script)中实现嵌套Default Dictionary?
Apps Script 实现嵌套 DefaultDict 的问题解决
类版本报错:TypeError: Class constructor DefaultDict cannot be invoked without 'new'
问题原因
你创建嵌套结构时写了new DefaultDict(DefaultDict(DefaultDict(Array))),内层的DefaultDict(...)直接调用类构造函数却没加new——类构造函数必须通过new实例化,直接调用会触发该错误。另外,就算加了new,直接传入实例也会导致所有新键共享同一个对象,正确做法是传入工厂函数,让每次需要默认值时动态生成新实例。
正确的类版本实现
class DefaultDict { constructor(defaultFactory) { this.defaultFactory = defaultFactory; this.map = new Map(); } get(key) { if (!this.map.has(key)) { // 调用工厂函数生成新默认实例,避免共享 const defaultValue = typeof this.defaultFactory === 'function' ? this.defaultFactory() : this.defaultFactory; this.map.set(key, defaultValue); } return this.map.get(key); } set(key, value) { this.map.set(key, value); return this; } }
嵌套使用示例
// 三层嵌套:最内层为数组 const nestedDict = new DefaultDict(() => new DefaultDict(() => new DefaultDict(() => []))); // 测试数据 nestedDict.get('a').get('b').get('c').push(1); console.log(nestedDict.get('a').get('b').get('c')); // 输出 [1] console.log(nestedDict.get('a').get('d').get('c')); // 输出 [],是独立的新数组
函数版本:不同层级共享对象的异常
问题原因
你之前的函数版本应该是直接将传入的默认值(如数组、子字典)赋值给新键,而非每次生成新实例。这样所有新创建的键都会共享同一个对象,导致修改一处影响其他层级。
修复后的函数版本实现
function DefaultDict(defaultFactory) { const map = new Map(); return { get(key) { if (!map.has(key)) { // 用工厂函数动态生成新默认值,避免共享 const defaultValue = typeof defaultFactory === 'function' ? defaultFactory() : defaultFactory; map.set(key, defaultValue); } return map.get(key); }, set(key, value) { map.set(key, value); return this; } }; }
嵌套使用示例
// 三层嵌套:最内层为数组 const nestedDict = DefaultDict(() => DefaultDict(() => DefaultDict(() => []))); // 测试数据 nestedDict.get('x').get('y').get('z').push(5); console.log(nestedDict.get('x').get('y').get('z')); // 输出 [5] console.log(nestedDict.get('x').get('y').get('w')); // 输出 [],独立的新数组
核心要点
不管是类版本还是函数版本,实现嵌套DefaultDict的关键是使用工厂函数(返回新实例的函数)作为默认值生成器,而非直接传入固定对象或实例。这样每次访问不存在的键时,都会创建全新实例,避免不同层级共享对象的问题。
内容的提问来源于stack exchange,提问作者Garfield Tong
相关产品推荐
相关产品推荐

