0

Suppose I have a source object that can be any arbitrary Javascript object, that may have properties that are themselves objects (or arrays or functions), nested to any level.

I want to perform a deep copy of this object into a new target object. However I only want to copy specific white-listed properties. These could be at any level in the source object.

Up till now I've been manually assigning white-listed properties in the source object to the target object. This doesn't seem very elegant and nor is it reusable. Can you please give me some guidance on implementing this using a more elegant and re-usable approach?

2
  • 1
    Can you give an example of an object and how you are currently doing it (actual code)? Commented Jul 5, 2015 at 20:51
  • Porque no recursion? Something like stackoverflow.com/questions/31215369/… except copying certain properties by name Commented Jul 5, 2015 at 21:13

1 Answer 1

2

This should do what you are looking for, including circular references.

EDIT: keep in mind this will get slower and slower for objects with lots of circular references inside! The lookup to see if a reference has been seen is a simple scan.

var util = require('util') var propertiesToCopy = { 'a' : true, 'b' : true, 'c' : true, 'd' : true, 'e' : true, 'f' : true, 'p1': true, 'p2': true, 'g' : true }; var obj; obj = { p2 : { a : 1, b : 2, c : {}, d : { f : 2 } }, p3 : 'hello' }; // circular obj.p1 = obj; obj.p2.d.e = obj; // sub-circular obj.p2.g = obj.p2.c; function getNewObjectFromObjects(obj, objects) { for (var i = 0; i < objects.length; i++) { if (obj === objects[i].old) return objects[i].new; } return false; } function whiteListedCopy(obj, whitelist, root, newRoot, objects) { var cloned = {}; var keys = Object.keys(obj); root = root || obj; newRoot = newRoot || cloned; objects = objects || [ {'old' : root, 'new': newRoot} ]; keys.forEach(function(val) { if (whitelist[val] === true) { if (typeof(obj[val]) === typeof({}) || typeof(obj[val]) === typeof([]) ) { var reference = getNewObjectFromObjects(obj[val], objects); if (reference === false) { cloned[val] = whiteListedCopy(obj[val], whitelist, root, newRoot, objects); objects.push({ 'old' : obj[val], 'new': cloned[val]}); } else { cloned[val] = reference; } } else { cloned[val] = obj[val]; } } }); return cloned; } var clonedObject = whiteListedCopy(obj, propertiesToCopy); console.log(util.inspect(clonedObject)); console.log('assert c and g are same reference:', clonedObject.p2.g === clonedObject.p2.c); console.log('assert p1 is circular:', clonedObject === clonedObject.p1); 
Sign up to request clarification or add additional context in comments.

1 Comment

This works really well. Thank you for taking the time to implement this solution.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.