我有以下问题:
库正在返回对象的引用。现在我不想只修改对象的单个部分,我想完全覆盖对象。
我的代码如下所示:
var options=getOptions();
options=newOptions;
// now do something with the new options.
但是当我运行此代码时,将删除引用并设置一个新引用。
那么如何将整个新对象复制到引用?
答案 0 :(得分:0)
您正在用options
替换您所指的对象,但这对任何对该库所具有的原始对象的引用都没有影响。你可以用getOptions
的返回值做 nothing ,它将用一个全新的对象替换lib所拥有的对象;你所能做的就是改变它给你的对象的状态(添加,更改和/或删除属性)。
除非库为您提供了一种在内部更改其引用的对象的方法,否则您无法完全替换该对象(无需修改库)。
以下是一个例子来说明:
// Emulating the library:
var lib = (function() {
var libOptions = {
name: "original"
};
return {
// The operation you said it has
getOptions: function() {
return libOptions;
},
// The operation it would need to have
setOptions: function(newOptions) {
libOptions = newOptions;
}
};
})();
var options = lib.getOptions();
options = {
name: "replaced"
};
console.log(options.name); // "replaced"
console.log(lib.getOptions().name); // "original"
lib.setOptions(options);
console.log(options.name); // "replaced"
console.log(lib.getOptions().name); // "replaced"
当库为您提供对象的引用时,您在内存中会有类似的内容:
libOptions−−+ | | +−−−−−−−−−−−−−−−−−−+ +−−>| (object) | | +−−−−−−−−−−−−−−−−−−+ | | name: "original" | options−−−−−+ +−−−−−−−−−−−−−−−−−−+
然后当您将options
设置为其他内容时:
+−−−−−−−−−−−−−−−−−−+ libOptions−−−−−>| (object) | +−−−−−−−−−−−−−−−−−−+ | name: "original" | +−−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−−−−−+ options−−−−−−−−>| (object) | +−−−−−−−−−−−−−−−−−−+ | name: "replaced" | +−−−−−−−−−−−−−−−−−−+
如您所见,设置options
对libOptions
中的库引用没有任何影响。
这就是lib必须提供setOptions
的原因。
当然,您可以再次更改对象的状态(前提是该库未提供防御性副本或冻结对象);
options.name = "updated";
这样做:
libOptions−−+ | | +−−−−−−−−−−−−−−−−−−+ +−−>| (object) | | +−−−−−−−−−−−−−−−−−−+ | | name: "updated" | options−−−−−+ +−−−−−−−−−−−−−−−−−−+
答案 1 :(得分:0)
我从您的问题中理解的是,您希望深度复制对象,以便原始对象完好无损,您可以修改其副本。如果错了,请纠正我。
var options=getOptions();
var copyOfObject = JSON.parse( JSON.stringify( options ));
答案 2 :(得分:0)
根据我的理解,你从一个库中获取一个对象,你想要更改一些键,同时保持对象的其余部分相同。
如果您想要更改的只有少数几个属性,则只需在您从库中接收的对象上分配值:
function getLibObject() {
return {
constantKey: 'constant',
overridenKey: 'to be overriden',
};
}
var libObject = getLibObject();
libObject.overridenKey = "has been overriden";
libObject.newKey = "A new key has been added";
console.log(JSON.stringify(combinedObject)); //{"constantKey":"constant","overridenKey":"has been overriden","newKey":"A new key has been added"}
如果要更改的对象中的键只有一个深度,则可以使用Object.assign
创建一个新的“浅合并”对象。 (根据您要支持的浏览器,您可能需要填充)
function getLibObject() {
return {
constantKey: 'constant',
overridenKey: 'to be overriden',
};
}
var libObject = getLibObject();
var newOptions = {
overridenKey: 'has been overriden',
newKey: 'A new key has been added'
};
var combinedObject = Object.assign({}, libObject, newOptions);
console.log(JSON.stringify(combinedObject)); //{"constantKey":"constant","overridenKey":"has been overriden","newKey":"A new key has been added"}
如果您希望合并的深度超过一个级别,Object.assign
将无效。您可以使用[Lodash merge]等实用程序功能或使用某些SO answers which solve this
function getLibObject() {
return {
constantKey: 'constant',
nestedKey: {
deepConstantKey: 'This is nested at the second level and should not change',
deepOverrideKey: 'This is nested at the second level and should be overriden'
}
};
}
var libObject = getLibObject();
var newOptions = {
nestedKey:{
deepOverrideKey: 'This value has been overriden'
}
};
var combined = _.merge({}, libObject, newOptions);
console.log(JSON.stringify(combined))
//{"constantKey":"constant","nestedKey":{"deepConstantKey":"This is nested at the second level and should not change","deepOverrideKey":"This value has been overriden"}}
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.5/lodash.min.js"></script>
答案 3 :(得分:0)
感谢您的帮助。我理解这个问题。
我现在以非常脏的方式解决了这个问题...... 当我有修改选项时,我会销毁lib对象并创建一个新对象。这不是好方法,而是解决方案。