代码之家  ›  专栏  ›  技术社区  ›  Flame_Phoenix

这两行代码有什么区别?

  •  3
  • Flame_Phoenix  · 技术社区  · 6 年前

    背景

    今天服务器着火了,因为应用程序崩溃了。在检查服务器之后,我发现内存一直在增加,这导致pm2最终终止并重新启动进程。

    代码

    这是因为我修好了。原始代码如下:

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

    看到这一点后,我想:“这肯定是一个印刷错误,而最初的创造者的意思是其他的东西,像这样”:

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

    问题

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

    我被吹走了…显然我得把它还原成原来的版本…

    问题

    这两条线有什么区别?

    2 回复  |  直到 6 年前
        1
  •  6
  •   T.J. Crowder    6 年前

    第一个写的 {} this.cache[script] 如果没有财产 this.cache 变量中的名称 script (或者有,但它的价值是错误的)。第二个没有。

    因此,这意味着如果您多次调用此代码(或将其放在多个位置),使用第一个代码,所有这些代码最终都将共享一个对象(存储在 this.cache[脚本] ,但是使用第二个代码,它们都将创建和使用自己的新对象。

    这就是为什么内存膨胀的原因,代码从来没有缓存对象并不断地创建新的对象。

    例子:

    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> 被评估,其中 <价值> 是步骤2的结果。所以 42个 分配给 b 是的。

    但是没有 a = 其中一部分:

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

    只是

    1. 表达 A 42 被计算,从而得到 42个 自从 未定义42 42个 .
    2. 表达 B=<值> 被评估,其中 <价值> 是步骤1的结果。所以 42个 分配给 是的。

    …离开 不变。

        2
  •  2
  •   Salman Arshad    6 年前

    让我们添加一些括号:

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

    这一行是 东西:

    1. 初始化 this.cache[script] 如果未定义
    2. 初始化 cache 变量的引用 this.cache[脚本]

    因此,对 隐藏物 变量也反映在 this.cache[脚本] 是的。

    替代代码将:

    1. 初始化 隐藏物 变量的引用 this.cache[脚本]
    2. 初始化 隐藏物 引用空白对象的变量

    根据上述情况,修改 隐藏物 变量会或不会反映在内部 this.cache[脚本] 是的。

    我猜破解的部分代码依赖于 this.cache... 是最新的,但是使用 隐藏物 变量更新…没有什么。