2017-01-24 6 views
0

Я хотел бы предоставить один объект и создать из него клонированный объект, но переопределяя его новыми значениями, не затрагивая оригинальный объект. Я хотел использовать immutablejs, чтобы объекты javascript были неизменными.Как слить два объекта с immutablejs?

Вот мой пример:

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

toObject() делает мелкую конверсию, идя только один ключ вниз.

Чтобы преобразовать descendants карту в простой объект JS, вы должны сделать:

map2.toObject().descendants.toObject()

Не очень элегантный и очень подвержен ошибкам. Вы могли бы просто сделать map2.toJS(), но это довольно неэффективно при работе с большими наборами данных.

В идеале, интересно, какой у вас вариант использования? Вы можете просто написать все свое приложение с помощью Immutable.js, не переходя на обычные объекты JavaScript (за исключением использования сторонних компонентов и библиотек). Это мощная библиотека, и любые преобразования, которые вы планируете делать с вашими данными, можно выполнить с помощью Immutable.

Если вы ищете неизменный deepMerge, вы можете использовать _.merge от lodash, который доступен даже в отдельном модуле. Просто обратите внимание, что первый аргумент в этой функции будет мутирован (слияния применяются к нему один за другим), поэтому передайте пустой объект {}, а затем ваши источники слияния.

+0

Спасибо. Это больше о читаемости. Да, я могу просто придерживаться immutablejs, но легче увидеть изменения, которые я хочу внести в структуру данных, как json-карту, как я уже сказал выше в моем примере. Я попробую примеры, которые вы предоставили. –

+0

ОК, поэтому lodash объединяет объекты так, как я хотел, но не замораживает объекты, поэтому они остаются изменчивыми, что не то, что я хочу. –

+0

.toJS работает красиво, но, как вы говорите, это потеря производительности. –

0

Я предложил альтернативное решение, используя чистый 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 и это заказное решение: взглянуть на лог консоли, чтобы увидеть разницу в мс. 8, 3, 1 мс скорость.

https://jsfiddle.net/ejyvpbwx/14/

 Смежные вопросы

  • Нет связанных вопросов^_^