闭包会复制值到新内存地址吗?修改闭包内变量会影响原内存吗?
闭包对引用类型变量的内存操作验证
我写了一段记忆化代码做概念验证,核心想搞清楚:闭包内修改变量时,是直接操作内存里的原始位置?还是创建闭包时会把值复制到新内存位置?
测试结论很明确:对于引用类型(比如这里的Map),闭包不会复制值,而是持有原始对象的引用——所以闭包里修改对象内容时,原始位置的对象会同步变化;但如果给原始变量重新赋值新对象,闭包持有的还是旧引用,不会跟着切换。
class Memoization { cacheInitValue = new Map(); memoize(f) { let cache = this.cacheInitValue; return function (...args) { let cacheKey = f.name + JSON.stringify(args); if (cache.has(cacheKey)) { return cache.get(cacheKey); } let result = f.apply(this, args); cache.set(cacheKey, result); return result; }; } } // 示例1:记忆化普通函数 // ---------------------------------------------------------------- function sum(...numbers) { console.log(`sum(${numbers.join(',')}) was called`); let total = 0; for (let n of numbers) { total += n; } return total; } // 使用方式: let memoSum = new Memoization(); let cacheSum = memoSum.memoize(sum); console.log(cacheSum(10,20)); // 首次调用,执行sum函数返回结果 console.log(cacheSum(10,20)); // 直接从缓存取结果,sum不会执行 // 查看闭包对memoSum对象属性的修改: console.log(memoSum.cacheInitValue, "(查看浏览器控制台)"); // 能看到Map的键已经被闭包修改了 // 接下来是关键测试:重置cacheInitValue后再调用记忆化函数 memoSum.cacheInitValue = new Map(); // 再次调用记忆化函数: console.log(cacheSum(10,20)); // sum会再次执行,因为闭包持有的是旧Map的引用
测试过程解析
- 第一次调用
cacheSum(10,20)时,结果存入cache(即memoSum.cacheInitValue),第二次调用直接取缓存,证明闭包能正常读写这个Map。 - 打印
memoSum.cacheInitValue看到内容变化,说明闭包和外部变量指向的是同一个Map对象,没有复制。 - 重置
memoSum.cacheInitValue为新Map后,cacheSum再次调用时会重新执行sum——因为闭包里的cache变量还是指向原来的旧Map,新Map和闭包没有关联。
内容的提问来源于stack exchange,提问作者Brainiac. jar
相关产品推荐
相关产品推荐

