Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deep clone without some fields

Let's I have next javascript object. Now I want clone it but without some fields. For example I want cloned object without field "lastName" and "cars.age"
Input

{
   "firstName":"Fred",
   "lastName":"McDonald",
      "cars":[
           {
              "type":"mersedes",
              "age":5
           },
           {
              "model":"bmw",
              "age":10
           }
       ]
}  

Output (cloned)

{
   "firstName":"Fred",
   "cars":[
       {
          "model":"mersedes"
       },
       {
          "model":"bmw"
       }
   ]
}   

I can do something like

var human = myJson   
var clone = $.extend(true, {}, human)  
delete clone.lastName  
_.each(clone.cars, function(car))  
{  
   delete car.age  
}  

Do you know easier solution?

like image 890
Ilya Avatar asked Jan 11 '13 09:01

Ilya


People also ask

What is the difference between deep cloning and shallow cloning?

In Shallow copy, a copy of the original object is stored and only the reference address is finally copied. In Deep copy, the copy of the original object and the repetitive copies both are stored.

What is the most efficient way to deep clone an object in JavaScript?

Using the Json. Among the above mentioned three ways, for an object to be deep cloned, JSON. stringify() and JSON. parse() functions are used. The parse() method accepts a JSON String as a parameter and creates a JavaScript object accordingly.

Is spread operator deep copy?

For nested objects the spread operator will provide a deep copy to the first instance of the values but leaves all the nested data as shallow copies sharing a space in memory with original. Take note of this behavior!


1 Answers

If you don't mind adding to object prototypes, this is an easy solution. You may want to modify it some for your own use.

Object.prototype.deepOmit = function(blackList) {
  if (!_.isArray(blackList)) { 
    throw new Error("deepOmit(): argument must be an Array");
  }

  var copy = _.omit(this, blackList);
  _.each(blackList, function(arg) {
    if (_.contains(arg, '.')) {
      var key  = _.first(arg.split('.'));
      var last = arg.split('.').slice(1);
      copy[key] = copy[key].deepOmit(last);
    }
  });
  return copy;
};

Array.prototype.deepOmit = function(blackList) {
  if (!_.isArray(blackList)) { 
    throw new Error("deepOmit(): argument must be an Array");
  }

  return _.map(this, function(item) {
    return item.deepOmit(blackList);
  });
};

Then when you have an object like:

var personThatOwnsCars = {
   "firstName":"Fred",
   "lastName":"McDonald",
      "cars":[
           {
              "type":"mersedes",
              "age":5
           },
           {
              "model":"bmw",
              "age":10
           }
       ]
};

You can do magic like this.

personThatOwnsCars.deepOmit(["firstName", "cars.age"]);

Or even magic like this!

[person1, person2].deepOmit(["firstName", "cars.age"]);
like image 112
mwoods79 Avatar answered Oct 14 '22 11:10

mwoods79