英文:
Confused about _.memoize() implementation
问题
我正在学习不同实现的memoize函数,有些地方让我感到困惑。这里是代码的一个版本:
_.memoize = function(func) {
let cache = {};
return function() {
let arg = JSON.stringify(arguments); //arg是一个字符串化的数组
if(!(arg in cache)) {
cache[arg] = func.apply(this, arguments);
}
return cache[arg];
};
};
我对```cache[arg]```的理解是,```cache```对象有一个```arg```键,或者如果没有,函数调用```func.apply(this, arguments)```会成为```arg```键的属性。如果```arg```已经是```cache```的一个键,那么函数将返回```cache[arg]```的属性。
但是,```arg```不是一个包含字符串的数组吗?它是分配给```arguments```的字符串化版本吗?还是一个由```JSON.stringify```形成的非常长的单一字符串?
不同的参数是如何访问的?对我来说,这似乎意味着```cache```只有一个键,要么是一个数组,要么是一个长字符串。这意味着单个参数的标识将丢失在单个数据中,我不知道它们是如何被访问的。我猜想可能会使用for循环或forEach循环来访问每个参数,但实际上并没有发生,所以我不太清楚如何阅读这段代码。
英文:
I'm learning different implementations of the memoize function, and something is confusing me. Here is one version of the code:
_.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];
};
};
My understanding of cahce[arg]
is that the cache
object has a key of arg
, or if it doesn't, the function call of func.apply(this, arguments)
becomes the property at an arg
key. If arg
is already a key in cache
, than the function returns the property at cache[arg]
.
Ok, but isn't arg
an array with a string in it? Assigned to a stringified version of arguments
? Or is it a super long, single string formed by JSON.stringify
?
How are the different arguments accessed? To me, this seems like the cache
has a single key of either an array or a long string. Which means the identity of the individual arguments would be lost in a single piece of data, and I don't see how they are being accessed. I guess I would assume a for loop or forEach would loop through to access each argument, but that's not happening, so I don't really know how to read this.
答案1
得分: 2
>好的,但是arg不是一个包含字符串的数组吗?
不,实际上是:
>还是它是一个由`JSON.stringify`形成的超长单字符串吗?
是的。例如,如果你对一个函数进行记忆化处理,然后用以下方式调用它:
```javascript
foo(1, 2)
foo(3, 4, 5)
foo('str')
然后缓存键将由以下字符串组成:
{"0":1,"1":2}
{"0":3,"1":4,"2":5}
{"0":"str"}
每一行都唯一标识了特定参数组合;在唯一有序的参数数量和生成的字符串化键之间存在一对一映射。没有丢失任何信息;参数可以转换成表示这些参数的单个字符串并不意味着任何关于参数(它们的顺序或值)的信息消失;它只是以一种不同的格式,即字符串的格式,放入缓存中以使其工作。(一一对应是数学和算法中的非常有用的技术之一。这只是它的一个实例。)
>我猜我会假设一个for循环或forEach会循环访问每个参数,但这并没有发生
那个循环确实发生了,它只是在底层使用JSON.stringify
实现的原生代码。但它只需完成一次。一旦有序的参数集被转换为字符串,那么该字符串就可以用于唯一标识参数,因此可以在缓存中查找键,或者将其设置在缓存中。
<details>
<summary>英文:</summary>
>Ok, but isn't arg an array with a string in it?
No, it is actually:
>Or is it a super long, single string formed by `JSON.stringify`?
Yes. For example, if you memoize a function and then call it with
foo(1, 2)
foo(3, 4, 5)
foo('str')
the cache keys will then be composed of the following strings:
```none
{"0":1,"1":2}
{"0":3,"1":4,"2":5}
{"0":"str"}
Each such line uniquely identifies a particular combination of arguments; there is a one-to-one mapping between a unique ordered number of arguments and the resulting stringified key. No information is lost; the fact that the arguments can be converted into a single string representing those arguments does not mean that any information about the arguments (their order or value) goes away; it's just put into a different format, that of a string, for the cache to work. (One-to-one correspondence is an incredibly useful technique in mathematics and algorithms. This is just one instance of it.)
>I guess I would assume a for loop or forEach would loop through to access each argument, but that's not happening
That loop is happening, it's just implemented in native code, under the hood with JSON.stringify
. But it only has to be done one way. Once an ordered set of arguments has been turned into a string, that string can then be used to uniquely identify the arguments, so the key can then be either looked up on the cache, or set on the cache.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
function foo() {
console.dir(JSON.stringify(arguments));
}
foo(1, 2);
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论