解构对象在修改后丢失引用
Destructured object loses reference after being modified
赋值后对象引用丢失。任何以前的参考资料都不再相关。
我有以下内容:
// lib.js
const obj = { prop: { data: { some: 'empty' } } };
function loadObject() {
obj.prop.data = { some: 'load' };
}
modules.exports = { prop: obj.prop, data: obj.prop.data, loadObject() };
和
// main.js
const { prop, data, loadObject } = require('./lib');
loadObject();
console.log(prop.data); // data changed (new reference)
console.log(data); // data not changed (old reference)
如何修改 data
而不丢失它的初始引用?
PS:
我有一堆导入这个库的文件,它依赖于那个 data
。
我宁愿不将它替换为 prop.data
或在每个使用它的文件中重新阅读它。
让任何变量看似改变自己自己(作为图书馆的消费者会体验到)是非常不直观的,并且是为了代码清晰起见,经常被 linters 禁止 - 如果需要那种逻辑,请考虑导出 函数 而 returns 当前数据,例如
modules.exports = {
prop: obj.prop,
getData: () => obj.prop.data,
loadObject
};
(注意要导出函数,您只需要引用函数,而不是调用它)
虽然如果您使用的是 ES6 模块,可能 导出可变绑定,但这里不是这种情况,无论如何也不是一个好主意。
您用新对象替换了 data
。没有办法将引用旧对象的所有内容更改为指向新对象,所以如果你想保持完全相同 API,你必须就地更改对象而不是替换它——也许像你一样之前做过:
// if it’s a single property that’s the same before and after
function loadObject() {
obj.prop.data.some = 'load';
}
// if the properties before are a subset of the properties after
function loadObject() {
Object.assign(obj.prop.data, { some: 'load' });
}
// if you need to change the set of properties entirely
function loadObject() {
for (const key of Object.keys(obj.prop.data)) {
delete obj.prop.data[key];
}
Object.assign(obj.prop.data, { some: 'load' });
}
问题与不同的模块系统或对象解构无关。请看下面的例子。
const obj = {prop: {data: {some: 'empty'}}};
const objRef = obj.prop.data;
console.log(objRef);
obj.prop.data.some = 'not empty';
console.log(objRef);
obj.prop.data = {other: 'hello!'};
console.log(objRef);
console.log(obj);
请记住,每次使用括号表示法创建对象时 {}
您都在隐式实例化一个新的 "independent" 对象。这对于您示例中的嵌套对象仍然有效。事实上,您有多个对象的多个嵌套引用。
嵌套对象的'name'(父对象的键)充当一个变量,其中包含您使用{}
实例化的新对象的引用。
我知道这可能看起来令人困惑(因为它确实如此),但如果您按照前面的代码片段进行操作,我相信您会明白的。 objRef
保留 "independent" 对象 {some: 'empty'}
的引用,同时作为引用存储在所有其他对象中,直到主对象 obj
。在这一行中:obj.prop.data = {other: 'hello!'};
我们从主要对象中完全擦除 {some: 'empty'}
引用,但它保留在 objRef
中,这将是该对象唯一剩余的引用。我们将 objRef
与 obj
分开。
- 总结:
每次使用{}
-> 等同于 -> new Object()
obj.prop.data.some = 'not empty';
-> 更改 属性 值。将在 data: {}
对象的所有引用中看到。
obj.prop.data = {other: 'hello!'};
-> 完全替换主对象中的 data: {}
对象引用(销毁引用)(仍保留在 objRef
中)。
如果不清楚我可以尝试用不同的方式解释它。请告诉我。
赋值后对象引用丢失。任何以前的参考资料都不再相关。
我有以下内容:
// lib.js
const obj = { prop: { data: { some: 'empty' } } };
function loadObject() {
obj.prop.data = { some: 'load' };
}
modules.exports = { prop: obj.prop, data: obj.prop.data, loadObject() };
和
// main.js
const { prop, data, loadObject } = require('./lib');
loadObject();
console.log(prop.data); // data changed (new reference)
console.log(data); // data not changed (old reference)
如何修改 data
而不丢失它的初始引用?
PS:
我有一堆导入这个库的文件,它依赖于那个 data
。
我宁愿不将它替换为 prop.data
或在每个使用它的文件中重新阅读它。
让任何变量看似改变自己自己(作为图书馆的消费者会体验到)是非常不直观的,并且是为了代码清晰起见,经常被 linters 禁止 - 如果需要那种逻辑,请考虑导出 函数 而 returns 当前数据,例如
modules.exports = {
prop: obj.prop,
getData: () => obj.prop.data,
loadObject
};
(注意要导出函数,您只需要引用函数,而不是调用它)
虽然如果您使用的是 ES6 模块,可能 导出可变绑定,但这里不是这种情况,无论如何也不是一个好主意。
您用新对象替换了 data
。没有办法将引用旧对象的所有内容更改为指向新对象,所以如果你想保持完全相同 API,你必须就地更改对象而不是替换它——也许像你一样之前做过:
// if it’s a single property that’s the same before and after
function loadObject() {
obj.prop.data.some = 'load';
}
// if the properties before are a subset of the properties after
function loadObject() {
Object.assign(obj.prop.data, { some: 'load' });
}
// if you need to change the set of properties entirely
function loadObject() {
for (const key of Object.keys(obj.prop.data)) {
delete obj.prop.data[key];
}
Object.assign(obj.prop.data, { some: 'load' });
}
问题与不同的模块系统或对象解构无关。请看下面的例子。
const obj = {prop: {data: {some: 'empty'}}};
const objRef = obj.prop.data;
console.log(objRef);
obj.prop.data.some = 'not empty';
console.log(objRef);
obj.prop.data = {other: 'hello!'};
console.log(objRef);
console.log(obj);
请记住,每次使用括号表示法创建对象时 {}
您都在隐式实例化一个新的 "independent" 对象。这对于您示例中的嵌套对象仍然有效。事实上,您有多个对象的多个嵌套引用。
嵌套对象的'name'(父对象的键)充当一个变量,其中包含您使用{}
实例化的新对象的引用。
我知道这可能看起来令人困惑(因为它确实如此),但如果您按照前面的代码片段进行操作,我相信您会明白的。 objRef
保留 "independent" 对象 {some: 'empty'}
的引用,同时作为引用存储在所有其他对象中,直到主对象 obj
。在这一行中:obj.prop.data = {other: 'hello!'};
我们从主要对象中完全擦除 {some: 'empty'}
引用,但它保留在 objRef
中,这将是该对象唯一剩余的引用。我们将 objRef
与 obj
分开。
- 总结:
每次使用{}
-> 等同于 -> new Object()
obj.prop.data.some = 'not empty';
-> 更改 属性 值。将在 data: {}
对象的所有引用中看到。
obj.prop.data = {other: 'hello!'};
-> 完全替换主对象中的 data: {}
对象引用(销毁引用)(仍保留在 objRef
中)。
如果不清楚我可以尝试用不同的方式解释它。请告诉我。