这两行代码有什么区别?

时间:2018-07-12 11:53:06

标签: javascript node.js

背景

今天,由于应用崩溃,服务器着火了。检查服务器后,我发现内存不断增加,这导致PM2最终终止并重新启动该过程。

代码

这是因为我进行了修复。原始代码如下:

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

看到我的想法之后:“当然这是一个错字,而原始创作者的意思是其他的,像这样”:

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

问题

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

我被吓死了...显然我不得不将其还原为原始版本...

问题

这两行之间有什么区别?

2 个答案:

答案 0 :(得分:6)

如果{}中没有名称为变量this.cache[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求值,由于42undefined || 42,因此得出值42
  2. 计算表达式a = <value>,其中<value>是步骤1的结果,因此42被分配给a。该表达式的结果是分配的值(42)。
  3. 计算表达式b = <value>,其中<value>是步骤2的结果。因此42被分配给b

但没有其中的a =部分:

let a, b;
b = a || 42;

只是

  1. 对表达式a || 42求值,由于42undefined || 42,因此得出值42
  2. 计算表达式b = <value>,其中<value>是步骤1的结果。因此42被分配给b

...保留a不变。

答案 1 :(得分:2)

让我们添加一些括号:

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

这行代码执行两项

  1. 初始化this.cache[script](如果未定义)
  2. 通过引用cache来初始化this.cache[script]变量

结果,对cache变量的修改也反映在this.cache[script]内部。

备用代码将是:

  1. 通过引用cache来初始化this.cache[script]变量
  2. 通过引用空白对象初始化cache变量

根据上述情况,对cache变量的修改将或不会反映在this.cache[script]内部。

我猜测中断的代码部分取决于this.cache...是最新的,但是使用cache变量的代码却没有更新。