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);