繁体   English   中英

解构变量值在模块之间不持久

[英]Destructured variable value not persisting between modules

在 Node JS 应用程序中的模块之间传递对象时,我得到了不一致的结果,或者可能只是误解了正在发生的事情!

在我的应用程序中,用下面的伪代码编写,首先在应用程序根目录中需要一个 lib 文件,然后是应用程序使用的其他服务,这些服务也需要在同一个库中。 然后在应用程序根目录中配置库——这会设置一个类变量 ( this.foo ),该变量在库中被初始化为一个空对象——最后调用其中一个服务中的方法。

foo 属性在服务文件的顶部被解构,如果我立即将其注销,我会得到一个空对象(如预期)。 当我调用服务方法时,在其他地方配置了 foo 并引用解构属性后,我仍然得到一个空对象。 如果相反,我不解构该属性,而只是在库 ( Lib ) 中需要,那么在我访问 Lib.foo 的方法中,我会看到配置的值(即如预期的那样)。

我怀疑解构变量是一个未被更新的值,所需的库是一个引用,但我读过的所有内容都表明没有任何值通过值传递。 任何指针将不胜感激!

// main.js
// ========
const lib = require('./lib');
const service = require('./service');
lib.configure({ foo: "bar"});
service.run();


// service.js
// ========
const Lib = require('./lib');     // This is for the example only
const { foo } = require('./lib'); // I'd prefer to just do this

console.log(Lib.foo); // {} as expected
console.log(foo);     // {} as expected

class Service {
    run() {
        console.log(foo);    // {} - should be "bar"
        console.log(Lib.foo) // "bar" as expected
    }
}
module.exports = new Service();


// lib.js
// ======
class Lib {
    constructor() {
        this.foo = {};
    }
    configure({ foo }) {
        this.foo = foo;
    }
}
module.exports = new Lib();

这是正确的行为。

=运算符(赋值)的作用是更新指向包含新值的新内存位置的指针,它不会更改我们当前指向的值。

对于字符串等原语,一般的实现是在变量重新分配期间实际复制整个值。

额外:这通常称为字符串实习

下面是一个例子:

 var x = "123"; // point the variable named "x" to a memory location containing the string "123" var y = x; // point the variable named "y" to a new memory location into which we copy the data from the memory location that "x" is pointing to x = "456"; // point the variable named "x" to a new memory location that that contains the value "456" console.log(y); // still "123", "y" still points to a memory location containing the copy of "123"

这是正在发生的事情的图表。

var x = "123";

情况1

var y = x;

案例2

x = "456";

案例2

注意:最初的“123”仍然留在内存中,除了没有任何东西指向它,所以垃圾收集器最终会清理它。

在对象的情况下,情况有点不同。 我们不是复制值,而是复制指向保存该值的内存位置的指针,但重新分配的行为相同。

 var x = {}; // point the variable named "x" to a memory location containing the empty object var y = x; // point the variable named "y" to the same memory location that "x" is pointing to x = { name: "foo" }; // point the variable named "x" to a new memory location that contains the object { name: "foo" } console.log(y); // still {}, "y" still points to a memory location containing the empty object

这是正在发生的事情的图表:

var x = {};   

情况1

var y = x;

案例2

x = { name: "foo" };

案例3

当您从Lib实例中解构foo时,它与该实例内部的foo ,它是一个新变量,指向与内部变量相同的内存位置。 此位置包含{}

当您调用.configure ,您正在更新内部值所指向的内存位置,但解构变量仍指向包含{}旧位置。

如果您要更新foo指向的对象而不是引用本身,则一切都会按您的预期工作:

configure({ foo }) {
    Object.assign(this.foo, foo);
}

我建议不要对像上面那样希望在更新中保持状态的持久 getter 进行解构。 拥有这些额外变量会增加复杂性(因为它增加了要维护的引用数量),并且还会导致内存泄漏(陈旧引用指向未使用的数据,这会阻止垃圾收集)。

此外,从类中解构方法可能会导致上述错误以及this意外行为。

如果您总是调用Lib.foo您将省去一些麻烦。

所以我认为你混淆了引用和值。 为什么{} FOO的值不会改变,而Lib.foo的价值做的原因是因为在foo的情况下,你在那个时候分配Lib.foo的值的副本。 如果您想改变 Lib 的数据并使其传播,您将需要使用该对象(而不是像您目前所做的那样解构参数)。

希望这可以帮助!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM