关于_.memoize()函数实现的疑问:参数缓存逻辑解析
关于memoize实现中参数序列化的疑问解析
先看你贴出的memoize实现代码:
_.memoize = function(func) { let cache = {}; return function() { let arg = JSON.stringify(arguments); //arg is an stringified array if(!(arg in cache)) { cache[arg] = func.apply(this, arguments); } return cache[arg]; }; };
你对cache核心逻辑的理解是对的:如果缓存里没有当前参数对应的键,就执行函数并把结果存进缓存;有就直接返回缓存值。下面针对你的疑问逐一解释:
1. arg到底是什么类型?
JSON.stringify(arguments)的结果是一个长字符串,不是数组。因为JSON.stringify的作用就是把任意可序列化的JS值转换成JSON格式的字符串。
举个例子,当你调用被memoize包装后的函数时传入(1, "test", {id: 3}),arguments是一个类数组对象,JSON.stringify会把它转换成字符串:"[1,\"test\",{\"id\":3}]"。
2. 为什么不用遍历参数,这样的键能区分不同参数组合吗?
这个实现的核心是用参数组合的唯一字符串标识作为缓存键,而JSON.stringify(arguments)刚好能生成这个标识:
- 不同的参数顺序、类型、值,都会生成不同的字符串。比如
(1,2)序列化后是"[1,2]",(2,1)是"[2,1]",这两个是完全不同的键,不会混淆。 - 不需要遍历参数拼接,是因为
JSON.stringify已经帮我们完成了「把所有参数打包成唯一字符串」的工作。它会遍历arguments这个类数组的所有元素,把整个参数序列转换成一个能代表当前参数组合的字符串,自然就不需要手动循环了。
当然这个实现也有局限性,比如如果参数里有不能被JSON序列化的值(比如函数、Symbol、循环引用对象),JSON.stringify会失败或者生成不准确的字符串,导致缓存失效,但这是另一个话题了。
内容的提问来源于stack exchange,提问作者GloriousKaboom
相关产品推荐
相关产品推荐

