我想提供一个对象并从中创建一个克隆对象,但是在不影响原始对象的情况下覆盖新值。我想使用immutablejs来确保javascript对象是不可变的。
以下是我的例子:
var map1 = Immutable.fromJS({
selector:'DYNAMIC',
descendants:{
icon:'x',
headingLink:'DYNAMIC',
text:'y',
readMoreLink:'z'
}
});
var map2 = map1.mergeDeep({
selector:'NEW VALUE',
descendants:{
headingLink:'NEW VALUE'
}
}).toObject();
我期待map2输出:
{
selector:'NEW VALUE',
descendants:{
icon:'x',
headingLink:'NEW VALUE',
text:'y',
readMoreLink:'z'
}
}
相反,我得到了ownerID和__altered等奇怪的组合:
{
selector:'NEW VALUE',
descendants:
__altered: false,
__hash:undefined,
__ownerID:undefined,
_root:pt,
size:4
}
}
任何有助于完成这项工作的建议都将不胜感激。如果immutablejs不能做到这一点,那么也许是另一个库。
答案 0 :(得分:1)
toObject()
进行浅层转换,只关闭一个键。
要将descendants
Map转换为普通JS对象,您必须执行以下操作:
map2.toObject().descendants.toObject()
不是很优雅,而且非常容易出错。你可以做map2.toJS()
,但是如果处理大量数据则效率很低。
理想情况下,我想知道你的用例是什么?您可以使用Immutable.js编写整个应用程序,而无需转换为纯JavaScript对象(除了与第三方组件和库一起使用)。它是一个功能强大的库,您计划对数据进行的任何转换都可以使用Immutable完成。
如果你只是在寻找一个不可变的deepMerge
,你可以使用lodash中的_.merge
,它甚至可以作为一个单独的模块使用。请注意,该函数中的第一个参数将被突变(合并将逐个应用于它),因此传入一个空对象{}
,然后传入合并源。
答案 1 :(得分:1)
我使用纯javascript提供了另一种解决方案。这适用于小物体。我不确定这会在多大程度上影响大型物体的性能,但它看起来非常快,几乎相同,如果不比lodash快一点。与lodash相比的优势在于它强制对象不可变。
var __ = {
clone: function(obj){
var inst;
if(Array.isArray(obj)){
inst = [];
obj.forEach(function(item){
inst.push(__.clone(item))
});
}else if(typeof obj === 'object'){
inst = {};
for(key in obj){
inst[key] = __.clone(obj[key]);
}
inst = Object.freeze(inst);
}else{
inst = obj; // function, boolean, string, int, flt, date etc...
}
// make this object immutable, so it cannot be changed.
return inst;
},
recurseFreezeNew: function(objNew){
var isArr = Array.isArray(objNew);
if(!isArr && typeof objNew === 'object'){
objNew = Object.freeze(objNew);
for(key in objNew){
objNew[key] = __.recurseFreezeNew(objNew[key]);
}
}else if(isArr){
var self = this;
objNew.forEach(function(item){
item = __.recurseFreezeNew(item);
});
}
return objNew;
},
recurseMerge: function(objModel, objNew){
var mergedResult;
var key;
var isModelArray = Array.isArray(objModel);
var isNewArray = Array.isArray(objNew);
var isModelObj = (!isModelArray && typeof objModel === 'object');
var isNewObj = (!isNewArray && typeof objNew === 'object');
var isBothObject = (isModelObj && isNewObj);
if(isBothObject){
mergedResult = {};
for(key in objModel){
if(!objNew[key]){
mergedResult[key] = objModel[key]; //keep existing...
}else{
mergedResult[key] = __.recurseMerge(objModel[key], objNew[key]); // override new value
}
}
for(key in objNew){
if(!objModel[key]){
mergedResult[key] = objNew[key]; // add new that don't exist...
}
}
mergedResult = Object.freeze(mergedResult);
}else{
objNew = __.recurseFreezeNew(objNew);
mergedResult = objNew;
}
return mergedResult;
}
};
var immutableMerge = function(){
var arr = Array.prototype.slice.call(arguments);
var merged = __.clone(arr[0]);
for(var i=1, intLen = arr.length; i < intLen; ++i){
merged = __.recurseMerge(merged, arr[i]);
}
return merged;
}
var merged = immutableMerge({
'a':'default',
'b':'default'
},{
a:'NEW VALUE'
});
比较immutablejs,lodash和此自定义解决方案的示例: 查看控制台日志以查看ms差异。 8,3,1毫秒的速度。