Last active
November 4, 2019 05:21
-
-
Save joe-oli/0d1bf9a578e83901b99046d76eddf244 to your computer and use it in GitHub Desktop.
JS Objects - merging
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//c. 2011 | |
Javascript's Object doesn't have any native merge operation. If you have two objects, say | |
{a:1, b:2} | |
{c:3, d:4} | |
And want to get | |
{a:1, b:2, c:3, d:4} | |
As far as I know, you have to iterate through the objects. That is to say that you decide on either a merge left or merge right strategy and then you do something like (simplified) | |
for (key in object2) { | |
object1[key] = object2[key]; | |
} | |
/// | |
Example#2: Merge two JavaScript objects | |
Extend a JavaScript object with the key/value pairs of another. | |
With the following helper, you can merge two objects into one new object: | |
function extend(obj, src) { | |
for (var key in src) { | |
if (src.hasOwnProperty(key)) obj[key] = src[key]; | |
} | |
return obj; | |
} | |
// example | |
var a = { foo: true }, b = { bar: false }; | |
var c = extend(a, b); | |
console.log(c); | |
// { foo: true, bar: false } | |
This is typically useful when merging an options dict with the default settings in a function or a plugin. | |
If support for IE 8 is not required, you may use Object.keys for the same functionality instead: | |
function extend(obj, src) { | |
Object.keys(src).forEach(function(key) { obj[key] = src[key]; }); | |
return obj; | |
} | |
This involves slightly less code and is a bit faster. | |
============ | |
#3 | |
Use spread Syntax: | |
Wrap any objects you'd like merged into one with braces ({}): | |
const person = { name: 'David Walsh', gender: 'Male' }; | |
const tools = { computer: 'Mac', editor: 'Atom' }; | |
const summary = {...person, ...tools}; | |
/* | |
Object { | |
"computer": "Mac", | |
"editor": "Atom", | |
"gender": "Male", | |
"name": "David Walsh", | |
} | |
*/ | |
Note also applies to more than 2 objects. | |
const person = { name: 'David Walsh', gender: 'Male' }; | |
const tools = { computer: 'Mac', editor: 'Atom' }; | |
const attributes = { handsomeness: 'Extreme', hair: 'Brown', eyes: 'Blue' }; | |
const summary = {...person, ...tools, ...attributes}; | |
/* | |
Object { | |
"computer": "Mac", | |
"editor": "Atom", | |
"eyes": "Blue", | |
"gender": "Male", | |
"hair": "Brown", | |
"handsomeness": "Extreme", | |
"name": "David Walsh", | |
} | |
*/ | |
In the case of a key collision, the right-most (last) object's value wins out: | |
const person1 = { name: 'David Walsh', age: 33 }; | |
const person2 = { name: 'David Walsh Jr.', role: 'kid' }; | |
const merged = {...person1, ...person2} | |
/* | |
Object { | |
"name": "David Walsh Jr.", | |
"age": 33, | |
"role": "kid", | |
} | |
*/ | |
========== | |
#4 | |
use Object.assign to accomplish the same; | |
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign | |
(but the spread operator makes things a bit shorter if you don't mind a slightly less descriptive syntax!) | |
Syntax: | |
Object.assign(target, sources); | |
where ...sources represents the source object(s). | |
Example: | |
var obj1 = {name: 'Daisy', age: 30}; | |
var obj2 = {name: 'Casey'}; | |
Object.assign(obj1, obj2); | |
console.log(obj1.name === 'Casey' && obj1.age === 30); | |
Object.assign(target, source1, source2, ...) method copies all the enumerable own property of source object to target object and returns the target object. | |
let obj1 = { | |
name: 'prashant', | |
age: 23, | |
} | |
let obj2 = { | |
qualification: 'BSC CS', | |
loves: 'Javascript' | |
} | |
let merge = Object.assign({}, obj1, obj2);; | |
console.log(merge); | |
/* | |
Object { | |
age: 23, | |
loves: "Javascript", | |
name: "prashant", | |
qualification: "BSC CS" | |
} | |
*/Copy | |
We have used an empty object {} as a target and passed the sources objects which should be merged in target. | |
======== | |
#5. | |
There are other libraries available which you can use to merge or two objects like | |
Jquery's $.extend() method | |
$.extend(deep, copyTo, copyFrom) can be used to make a complete deep copy of any array or object in javascript. | |
Lodash merge() method | |
which will merge objects and arrays by performing deep merge recursively. | |
================= | |
#6. Deep Merge Objects | |
To deep merge an object we have to copy the own properties and extended properties as well, if it exits. | |
The best way to do so is to create a custom function. | |
let merge = (...arguments) => { | |
// Variables | |
let target = {}; | |
// Merge the object into the target object | |
let merger = (obj) => { | |
for (let prop in obj) { | |
if (obj.hasOwnProperty(prop)) { | |
if (Object.prototype.toString.call(obj[prop]) === '[object Object]') { | |
// If we're doing a deep merge and the property is an object | |
target[prop] = merge(target[prop], obj[prop]); | |
} else { | |
// Otherwise, do a regular merge | |
target[prop] = obj[prop]; | |
} | |
} | |
} | |
}; | |
//Loop through each object and conduct a merge | |
for (let i = 0; i < arguments.length; i++) { | |
merger(arguments[i]); | |
} | |
return target; | |
}; | |
//USAGE: | |
let obj1 = { | |
name: 'prashant', | |
age: 23, | |
nature: { | |
"helping": true, | |
"shy": false | |
} | |
} | |
let obj2 = { | |
qualification: 'BSC CS', | |
loves: 'Javascript', | |
nature: { | |
"angry": false, | |
"shy": true | |
} | |
} | |
console.log(merge(obj1, obj2)); | |
/* | |
Object { | |
age: 23, | |
loves: "Javascript", | |
name: "prashant", | |
nature: Object { | |
angry: false, | |
helping: true, | |
shy: true | |
}, | |
qualification: "BSC CS" | |
} | |
*/ | |
We can combine both the function for shallow copy and deep copy together to create a single function which will perform merge based on the arguments passed. | |
If we will pass true as first argument then it will perform deep merge else it will perform shallow merge. | |
let merge = (...arguments) => { | |
// Variables | |
let target = {}; | |
let deep = false; | |
let i = 0; | |
// Check if a deep merge | |
if (typeof (arguments[0]) === 'boolean') { | |
deep = arguments[0]; | |
i++; | |
} | |
// Merge the object into the target object | |
let merger = (obj) => { | |
for (let prop in obj) { | |
if (obj.hasOwnProperty(prop)) { | |
if (deep && Object.prototype.toString.call(obj[prop]) === '[object Object]') { | |
// If we're doing a deep merge and the property is an object | |
target[prop] = merge(target[prop], obj[prop]); | |
} else { | |
// Otherwise, do a regular merge | |
target[prop] = obj[prop]; | |
} | |
} | |
} | |
}; | |
//Loop through each object and conduct a merge | |
for (; i < arguments.length; i++) { | |
merger(arguments[i]); | |
} | |
return target; | |
}; | |
let obj1 = { | |
name: 'prashant', | |
age: 23, | |
nature: { | |
"helping": true, | |
"shy": false | |
} | |
} | |
let obj2 = { | |
qualification: 'BSC CS', | |
loves: 'Javascript', | |
nature: { | |
"angry": false, | |
"shy": true | |
} | |
} | |
//Shallow merge | |
console.log(merge(obj1, obj2)); | |
/* | |
Object { | |
age: 23, | |
loves: "Javascript", | |
name: "prashant", | |
nature: Object { | |
angry: false, | |
shy: true | |
}, | |
qualification: "BSC CS" | |
} | |
*/ | |
//Deep merge | |
console.log(merge(true, obj1, obj2)); | |
/* | |
Object { | |
age: 23, | |
loves: "Javascript", | |
name: "prashant", | |
nature: Object { | |
angry: false, | |
helping: true, | |
shy: true | |
}, | |
qualification: "BSC CS" | |
} | |
*/ | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment