Javascript 没有闭包作用域的记忆

Javascript memoization without closure scope

Secrets of the JavaScript Ninja 中,作者提出了以下方案,用于在没有闭包的情况下记忆函数结果。他们通过利用函数是对象这一事实并在函数上定义一个 属性 来存储过去调用该函数的结果。

function isPrime(value) {
    if (!isPrime.answers) isPrime.answers = {};
    if (isPrime.answers[value] != null) {
        return isPrime.answers[value];
    }
    var prime = value != 1
    for (var i = 2; i < value; i++) {
        if (value % i === 0) {
            prime = false;
            break;
        }
    }
    return isPrime.answers[value] = prime;
}

我有两个问题

  1. 他们的逻辑对我来说很有意义,但是当我 运行 代码时,所发生的一切都是答案 属性 创建但没有添加任何东西 - 为什么?
  2. return isPrime.answers[value] = prime; 行对我来说很有趣,repl.it 在我使用它时会发出警告。在同一行中分配和返回全部不受欢迎吗?

1. Their logic makes sense to me, but when I run the code all that happens is the answers property is created but nothing gets added to it - why?

它对我来说似乎工作得很好。

console.log(isPrime(42));
console.log(isPrime.answers)

表明answers是一个非空对象:

function isPrime(value) {
    if (!isPrime.answers) isPrime.answers = {};
    if (isPrime.answers[value] != null) {
        return isPrime.answers[value];
    }
    var prime = value != 1
    for (var i = 2; i < value; i++) {
        if (value % i === 0) {
            prime = false;
            break;
        }
    }
    return isPrime.answers[value] = prime;
}

console.log(isPrime(42));
console.log(isPrime.answers)

2. [...] Is assigning and returning all in the same line frowned upon?

在这种情况下,赋值基本上是一个side effect,副作用是不受欢迎的。也就是说,赋值是表达式并返回赋值是语言的一个特性,只要负责任地使用它,为什么不呢。

Their logic makes sense to me

不应该。该方案仍然依赖于闭包,特别是函数所在范围内的 isPrime 变量。他们同样可以使用 var isPrimeAnswers = {}; 而不是 isPrime.answers = {}; (两者都应该放在在函数体之外)。

Is assigning and returning all in the same line frowned upon?

取决于你问的是谁,但并没有一致谴责这是一种不好的做法。你说搞笑,别人看得一头雾水,我个人觉得crystal明白了。如果你不喜欢代码高尔夫并且想安全起见,最好将它简单地分成两个语句:

isPrime.answers[value] = prime;
return prime;