Javascript - 从一个对象到另一个新对象的深层复制特定属性

时间:2015-07-05 20:15:09

标签: javascript arrays javascript-objects

假设我有一个源对象,它可以是任意Javascript对象,它可能具有本身对象(或数组或函数)的属性,嵌套到任何级别。

我想将此对象的深层副本执行到新的目标对象中。但是我只想复制特定的白名单属性。这些可以在源对象中的任何级别。

到目前为止,我一直在手动将源对象中列出白名单的属性分配给目标对象。这似乎不是很优雅,也不是可重复使用的。能否请您使用更优雅和可重复使用的方法为我提供一些指导?

1 个答案:

答案 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);
相关问题