这2行代码有什么区别?

3

背景

今天,服务器因为应用程序崩溃而出现故障。检查服务器后,我发现内存不断增加,导致PM2最终杀死并重启进程。

代码

这是由于我进行了修复造成的。原始代码如下:

const cache = this.cache[script] = this.cache[script] || {};

看到这个后,我想:“肯定是打错了,原始创作者的意思应该是这样的:”

const cache = this.cache[script] || {};

问题

这两行代码有什么区别?

问题描述

通过修复那一行代码后,内存开始增长并积累,直到填满整个服务器。

我很震惊...显然我不得不将其恢复为原始版本...

2个回答

5
如果在变量script的名称中没有属性(或者有但其值为假),第一个代码会将{}写入this.cache[script]。而第二个则不会。
这意味着如果您多次调用此代码(或在多个位置使用它),使用第一个代码,它们都将共享一个对象(存储在this.cache[script]上),但是使用第二个代码,它们将创建并使用自己的新对象。
这就是为什么您的内存会膨胀,因为代码从未缓存对象,而是不断创建新对象。
示例:

class Example {
  constructor() {
    this.cache = Object.create(null);
  }
  getTheCache1(script) {
    const cache = this.cache[script] || {};
    return cache;
  }
  getTheCache2(script) {
    const cache = this.cache[script] = this.cache[script] || {};
    return cache;
  }
}

const e1 = new Example();
const e1c1 = e1.getTheCache1("foo");
const e1c2 = e1.getTheCache1("foo");
console.log("e1c1 === e1c2? " + (e1c1 === e1c2));

const e2 = new Example();
const e2c1 = e1.getTheCache2("foo");
const e2c2 = e1.getTheCache2("foo");
console.log("e2c1 === e2c2? " + (e2c1 === e2c2));

一个更简单的例子:

let a; // a starts out undefined

console.log("const b = a || {};");
const b = a || {};
console.log("typeof a: " + typeof a); // "typeof a: undefined"
console.log("typeof b: " + typeof b); // "typeof b: object"
console.log("a === b? " + (a === b)); // "a === b? false"

console.log("const c = a = a || {};");
const c = a = a || {};
console.log("typeof a: " + typeof a); // "typeof a: object"
console.log("typeof c: " + typeof c); // "typeof c: object"
console.log("a === c? " + (a === c)); // "a === c? true"
.as-console-wrapper {
  max-height: 100% !important;
}

这一切都是因为赋值的结果就是被赋的值。所以在这里:
let a, b;
b = a = a || 42;

发生的情况如下:
  1. 计算表达式a || 42,结果为42,因为undefined || 42的结果是42
  2. 计算表达式a = <value>,其中<value>是步骤1的结果。所以42被赋值给a。该表达式的结果是被赋值的值(42)。
  3. 计算表达式b = <value>,其中<value>是步骤2的结果。所以42被赋值给b
但如果没有a =这一部分:
let a, b;
b = a || 42;

这只是关于IT技术的一些内容:

  1. 求值表达式a || 42,结果为42,因为undefined || 42 等于 42
  2. 求值赋值表达式b = <value>,其中<value> 是步骤1的结果。因此,42 被赋值给 b

...保持a不变。


像往常一样,解释得非常好。实际上我就是这么认为,但我需要确认一下。我上次看到双重赋值已经超过十年了……我想我被吓了一跳! - Flame_Phoenix

1
让我们加上一些括号:
const cache = (this.cache[script] = (this.cache[script] || {}));

这一行代码有两个作用:
  1. 如果未定义,初始化 this.cache[script]
  2. 使用指向 this.cache[script] 的引用初始化 cache 变量
因此,对 cache 变量的修改也会反映在 this.cache[script] 中。
备选代码将执行以下操作之一:
  1. 使用指向 this.cache[script] 的引用初始化 cache 变量
  2. 使用空对象的引用初始化 cache 变量
根据上述情况,对 cache 变量的修改可能会或不会反映在 this.cache[script] 中。
我猜测出问题的代码部分依赖于 this.cache... 是最新的,但使用 cache 变量的代码却没有更新任何内容。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接