模块之间不持久的解构变量值
Destructured variable value not persisting between modules
我在 Node JS 应用程序中的模块之间传递对象时得到不一致的结果,或者可能只是误解了发生了什么!
在我的应用程序中,用下面的伪代码编写,首先需要一个 lib 文件进入应用程序根目录,然后是应用程序使用的其他服务,这些服务也需要在同一个库中。然后在应用程序根目录中配置该库 - 这会设置一个 class 变量 (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();
这是正确的行为。
=
operator (the assignment) 所做的是更新指向包含新值的新内存位置的指针,它不会更改我们当前指向的值。
对于字符串等基元,一般实现是在变量重新分配期间实际复制整个值。
额外:这个通常叫做String interning
这是一个例子:
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";
var y = x;
x = "456";
注意:最初的“123”仍保留在内存中,只是没有任何内容指向它,所以 garbage collector 最终会清理它。
在对象的情况下,情况有点不同。我们不是复制值,而是将指针复制到保存该值的内存位置,但重新分配的行为相同。
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 = {};
var y = x;
x = { name: "foo" };
当您从 Lib
的实例中解构 foo
时,它与该实例内部的 foo
不同,它是一个指向与内部变量相同的内存位置。此位置包含 {}
.
当您调用 .configure
时,您正在更新内部值指向的内存位置,但解构变量仍指向包含 {}
.
的旧位置
如果您要更新 foo
指向的对象而不是引用本身,一切都会按您预期的那样工作:
configure({ foo }) {
Object.assign(this.foo, foo);
}
我建议不要像上面那样对持久性吸气剂进行解构,因为您希望在更新期间保持状态。拥有这些额外的变量会增加复杂性(因为它会增加要维护的引用数量)并且还会导致 memory leaks(过时的引用指向未使用的数据,这会阻止垃圾收集)。
此外,class 的解构方法可能会导致上述错误以及 this
.
的意外行为
如果您总是调用 Lib.foo
,您会省去一些麻烦。
所以我认为您混淆了引用和值。 { foo } 的值不变而 Lib.foo 的值不变的原因是因为在 foo 的情况下,您正在分配 Lib.foo 的值的副本当时。如果您想改变 Lib 的数据并传播它,您将需要使用该对象(而不是像您当前正在做的那样解构参数)。
希望对您有所帮助!
我在 Node JS 应用程序中的模块之间传递对象时得到不一致的结果,或者可能只是误解了发生了什么!
在我的应用程序中,用下面的伪代码编写,首先需要一个 lib 文件进入应用程序根目录,然后是应用程序使用的其他服务,这些服务也需要在同一个库中。然后在应用程序根目录中配置该库 - 这会设置一个 class 变量 (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();
这是正确的行为。
=
operator (the assignment) 所做的是更新指向包含新值的新内存位置的指针,它不会更改我们当前指向的值。
对于字符串等基元,一般实现是在变量重新分配期间实际复制整个值。
额外:这个通常叫做String interning
这是一个例子:
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";
var y = x;
x = "456";
注意:最初的“123”仍保留在内存中,只是没有任何内容指向它,所以 garbage collector 最终会清理它。
在对象的情况下,情况有点不同。我们不是复制值,而是将指针复制到保存该值的内存位置,但重新分配的行为相同。
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 = {};
var y = x;
x = { name: "foo" };
当您从 Lib
的实例中解构 foo
时,它与该实例内部的 foo
不同,它是一个指向与内部变量相同的内存位置。此位置包含 {}
.
当您调用 .configure
时,您正在更新内部值指向的内存位置,但解构变量仍指向包含 {}
.
如果您要更新 foo
指向的对象而不是引用本身,一切都会按您预期的那样工作:
configure({ foo }) {
Object.assign(this.foo, foo);
}
我建议不要像上面那样对持久性吸气剂进行解构,因为您希望在更新期间保持状态。拥有这些额外的变量会增加复杂性(因为它会增加要维护的引用数量)并且还会导致 memory leaks(过时的引用指向未使用的数据,这会阻止垃圾收集)。
此外,class 的解构方法可能会导致上述错误以及 this
.
如果您总是调用 Lib.foo
,您会省去一些麻烦。
所以我认为您混淆了引用和值。 { foo } 的值不变而 Lib.foo 的值不变的原因是因为在 foo 的情况下,您正在分配 Lib.foo 的值的副本当时。如果您想改变 Lib 的数据并传播它,您将需要使用该对象(而不是像您当前正在做的那样解构参数)。
希望对您有所帮助!