Javascript只分配源到目标对象的交集

时间:2017-10-29 12:35:08

标签: javascript ecmascript-6 lodash

我有两个对象,我想从源更新目标对象值,但只更新目标中已存在的值。

const target = {
    a: 1,
    b: 2,
    c: {
        c_a: 3,
        c_b: 4,
    }
}

const source = {
    a: 10,
    c: {
        c_a: 30,
        c_d: 50,
    },
    d: 60
}

const result = assignOnlyIntersection(target, source);

JSON.stringify(result)

// {
//    a: 10,
//    b: 2,
//    c: {
//        c_a: 30,
//        c_b: 4
//    }
// }

ES6 有一个好方法吗?如果没有,lodash是否有这方面的功能?如果不是如何以一种好的方式解决它?

5 个答案:

答案 0 :(得分:2)

一个简单的递归函数可以:

function assignOnlyIntersection(target, source) {
    if (Object(target) !== target || Object(source) !== source)
        return source;
    for (const p in source)
        if (p in target)
            target[p] = assignOnlyIntersection(target[p], source[p]);
    return target;
}

答案 1 :(得分:0)

您需要遍历target对象的键,检查source对象上是否有相同的键,如果是,请替换该值。如果你在路上找到一个物体,你也需要递归。

这样的事情可以完成这项工作:

const target = { a: 1, b: 2, c: { c_a: 3, c_b: 4 }};
const source = { a: 10, c: { c_a: 30, c_d: 50 }, d: 60 };

function assignOnlyIntersection(t, s) {
    Object
        .keys(s)
        .filter(k => k in t)
        .forEach(k => {
           if (typeof t[k] === 'object') {
               assignOnlyIntersection(t[k], s[k]);
           } else {
               t[k] = s[k];
           }
    });
    
    return t;
}

const result = assignOnlyIntersection(target, source);

console.log(JSON.stringify(result));

另请注意,如果您想支持替换0''等虚假值,则需要使用typeof t[k] !== 'undefined'检查是否存在。

正如@ghybs所指出的,如果您还想支持替换为undefined值,则需要通过in operator k in t进行检查。

答案 2 :(得分:0)

您可以通过检查对象来采取递归方法。

function deepAssign(target, source) {
    Object.keys(source).forEach(function (k) {
        var objectCount = [source, target]
                .map(o => o[k])
                .map(o => o && typeof o === 'object')
                .map(Boolean)
                .reduce((a, b) => a + b)

        if (!(k in target) || objectCount === 1) {
            return;
        }
        if (objectCount === 2) {
            return deepAssign(target[k], source[k]);
        }
        target[k] = source[k];
    });
    return target;
}

var source = { a: 10, c: { c_a: 30, c_d: 50, }, d: 60 },
    target = { a: 1, b: 2, c: { c_a: 3, c_b: 4, } };

console.log(deepAssign(target, source));
.as-console-wrapper { max-height: 100% !important; top: 0; }

答案 3 :(得分:0)

另一种ES6方法

<强>非变化的:

const intersector = (target = {}, source = {}) => {
  return Object.keys(source).reduce((acc, prop) => {
    if (target.hasOwnProperty(prop)) {
      if (typeof source[prop] === 'object' && source[prop] !== null) {
        acc[prop] = intersector(target[prop], source[prop]);
      }
      else {
        acc[prop] = source[prop];
      } 
    }
    return acc;
  }, {});
}

<强>变化的:

const intersector = (target = {}, source = {}) => {
  return Object.keys(source).reduce((acc, prop) => {
    if (target.hasOwnProperty(prop)) {
      if (typeof source[prop] === 'object' && source[prop] !== null) {
        acc[prop] = intersector(target[prop], source[prop]);
      }
      else {
        acc[prop] = source[prop];
      }
      target[prop] = acc[prop];
    }
    return acc;
  }, target);
};

答案 4 :(得分:0)

您可以结合使用Array.reduce()Object.keys() ES6功能来实现:

let target = {
a: 1,
b: 2,
c: {
    c_a: 3,
    c_b: 4,
}
}

let source = {
a: 10,
c: {
    c_a: 30,
    c_d: 50,
},
d: 60
}

const assignOnlyIntersection = (sourceObj, targetObj) => {
return Object.keys(targetObj).reduce((intersection, key) => { 
    intersection[key] = (typeof targetObj[key] === 'object') ? assignOnlyIntersection(sourceObj[key], targetObj[key]) : sourceObj[key] || targetObj[key];
    return intersection; 
}, {})
}

target = assignOnlyIntersection(source, target);

console.log(target);