假设我有一个源对象,它可以是任意Javascript对象,它可能具有本身对象(或数组或函数)的属性,嵌套到任何级别。
我想将此对象的深层副本执行到新的目标对象中。但是我只想复制特定的白名单属性。这些可以在源对象中的任何级别。
到目前为止,我一直在手动将源对象中列出白名单的属性分配给目标对象。这似乎不是很优雅,也不是可重复使用的。能否请您使用更优雅和可重复使用的方法为我提供一些指导?
答案 0 :(得分:2)
这应该可以满足您的需求,包括循环引用。
编辑:请记住,对于内部有大量循环引用的对象,这将变得越来越慢!查看是否已看到引用的查找是一个简单的扫描。
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);