2017-04-03 28 views
0

我想将两个对象合并到一个新对象中,如果两个对象都有它们,则覆盖一个对象。合并两个对象,但明确定义了可以设置的键

这对于ES6传播很容易,但在这种特殊情况下,我想使用一种仍然定义可以设置哪些密钥的方法。基本上创建一个在我的最终对象上允许的属性的“白名单”。 (利差,任何属性将被合并到新的对象中)。

有没有一种方法使用ES6 +来做到这一点?

两个对象:

var o1 = { 
    a: 'foo', 
    b: 'bar', 
    c: 'baz' 
} 

var o2 = { 
    a: 'pop', 
    bad_property: 'dont copy me' 
} 

var oMerged = { 
    a: 'pop', // I came from obj_2 
    b: 'bar', 
    c: 'baz' 
} 

合并方法:

// Method 1: Use spreads, problem is this hides the keys. 
var oMerged = { 
    ...o1, 
    ...o2 
}; 

// Method 2: Shows each key, but requires a ternary to check if obj_2 has the key. 
var oMerged = { 
    a: (o2.a !== undefined) ? o2.a : o1.a, 
    b: (o2.b !== undefined) ? o2.b : o1.b, 
    c: (o2.c !== undefined) ? o2.c : o1.c 
} 

// Method 3: Define what keys can be merged, but use a more concise syntax/possibly an ES6+ feature. 
??? 

编辑:显式表示,该对象应当具有可接受的性质的白名单。有很好的答案,但他们需要黑名单不可接受的属性。 “白名单”的原因是它向其他开发者展示了最终对象的形状。

+0

你确定你不是在寻找[对象。分配(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)?你能解释一下你需要什么吗? –

+0

再次查看Object.assign,但如果我没有记错,它会复制所有对象的所有枚举属性 - 因此它将包含obj_2中的'bad_property'。 –

+0

看看这个:[JavaScript过滤对象](http://stackoverflow.com/questions/5072136/javascript-filter-for-objects) – trincot

回答

0

尝试...

function (Obj1,Obj2) { 
 
    ['can','set','these'].forEach(key => Obj1[key] && (Obj2[key] = Obj1[key])) 
 
}

1

在这里你去,你可以使用factory()函数来创建不同的合并功能,每一个都有自己的一套允许的话,然后调用这些函数合并任意数量的对象。

const obj1 = { 
 
    a: 'foo', 
 
    b: 'bar', 
 
    c: 'baz' 
 
} 
 

 
const obj2 = { 
 
    a: 'pop', 
 
    bad_property: 'dont copy me' 
 
} 
 

 
const obj3 = { 
 
    another_one: 'test', 
 
    another_bad_property: 'dont copy this either' 
 
} 
 

 
const factory = allowed => { 
 
    return (...args) => { 
 
    const temp = {} 
 
    args.forEach(obj => { 
 
     Object.keys(obj).forEach(key => { 
 
     if (allowed.indexOf(key) !== -1) { 
 
      temp[key] = obj[key] 
 
     } 
 
     }) 
 
    }) 
 
    
 
    return temp 
 
    } 
 
} 
 

 
const mergeWith4AllowedKeys = factory(['a', 'b', 'c', 'another_one']) 
 
const merged = mergeWith4AllowedKeys(obj1, obj2, obj3) 
 

 
console.log(merged) 
 

 
const mergeWith3AllowedKeys = factory(['a', 'b', 'c']) 
 
const secondBatch = mergeWith3AllowedKeys(obj1, obj2) // only 2 
 

 
console.log(secondBatch)

+0

Thansk @motanelu这是一个非常可靠的答案 - 主要问题是它需要一个被禁止的属性列表。我想要一个可接受的属性的白名单,而不是禁止的属性的黑名单。目的是向其他开发人员展示最终对象的“形状”。 –

+1

更新了,现在你必须指定'factory()'函数的白名单... – motanelu

+0

@DonnyP它到底工作了吗? – motanelu

0

你可以使用一个omit功能(如this一个由lodash提供)没有某些键来创建一个对象的一个​​副本。然后,你可以合并该对象:

function omit(object, blacklist) { 
 
    return Object.keys(object).reduce((result, key) => { 
 
    if(!blacklist.includes(key)) { 
 
     result[key] = object[key]; 
 
    } 
 
    return result; 
 
    }, {}); 
 
} 
 

 
var o1 = { 
 
    a: 'foo', 
 
    b: 'bar', 
 
    c: 'baz' 
 
} 
 

 
var o2 = { 
 
    a: 'pop', 
 
    bad_property: 'dont copy me' 
 
} 
 

 
var blacklist = ['bad_property']; 
 
var merged = { 
 
    ...omit(o1, blacklist), 
 
    ...omit(o2, blacklist) 
 
}; 
 

 
console.log(merged);

0

这是ES2017 Spread and Rest实现,它是在typescript ^2.1

随着o1,当你拥有它o2支持比如,你可以写:

let merged = { ...o1, ...o2 }; 
// and then use Object rest as the dual of object spreads, to pick up the wanted properties 
let { bad_property, ...oMerged } = merged; 
+0

有趣,但是这不需要明确列出“坏”属性?基本上是黑名单而不是白名单? –

+0

是的我假设你可以在一些黑名单对象中使用它,并像'let {... badProps,... oMerged} = merged'一样使用它;' 所有其他不属于badProps的键都应该转到刚刚声明的' oMerge',但我还没有尝试过这个版本 – Vojtech

+0

好的,经过一番研究后,只有在使用其他运算符时明确键入“bad”属性时,此解决方案才有效 – Vojtech

0

这是最短方法我已经想出了可以让你

  1. 设置为了使被覆盖的属性
  2. 让你声明一下属性是在最后的对象接受
  3. 不需要为每个属性长ternaries

    // Step 1. merge all properties into a new object. 
    var oMerged = {...o1, ...o2}; 
    
    // Step 2. Explicitly use keys to assign 
    var oFinal = { 
        a: oM.a, 
        b: oM.b, 
        c: oM.c 
    }; 
    
+0

您的解决方案无法扩展......如果发生你有100个对象,每个对象有100个属性。 – motanelu