<script src='https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.min.js'></script>
<script src='https://unpkg.com/deepmerge@4.2.2/dist/umd.js'></script>
var a = { a: 'oh', b: 'my', c: { a: 'a', b: { c: 'c' } } };
var b = { c: { b: { d: 'a' }, c: { d: 'd' } } };
var c = _.merge({}, a, b);
var a = { a: 'oh', b: 'my', c: { a: 'a', b: { c: 'c' } } };
var b = { c: { b: { d: 'a' }, c: { d: 'd' } } };
var c = _.merge({}, a, b);
var a = { a: 'oh', b: 'my', c: { a: 'a', b: { c: 'c' } } };
var b = { c: { b: { d: 'a' }, c: { d: 'd' } } };
var c = deepmerge({}, a, b);
function isMergable(property) {
return Array.isArray(property) || typeof property === 'object'
}
function propertyTypesDoMatch(propA, propB) {
if (propA && propB) {
return propA.constructor.name === propB.constructor.name
}
return false
}
const basics = ['string', 'number', 'boolean', 'bigint', 'undefined', 'symbol', 'function']
function deepEqual(i1, i2) {
if (basics.includes(typeof i1) && typeof i1 === typeof i2) {
return i1 === i2
}
if (Array.isArray(i1) && Array.isArray(i2)) {
return i1.every((subItem) => arrayContainsSame(i2, subItem))
}
if (typeof i1 === typeof i2 && typeof i1 === 'object') {
return Object.entries(i1).every(([key, value]) => {
return deepEqual(value, i2[key])
})
}
return false
}
function arrayContainsSame(items, item) {
// skippable for loop makes it 1ms faster
for (let c = 0; c < items.length; c++) {
if (deepEqual(items[c], item)) {
return true
}
}
}
function mergeArrays(array1, array2) {
const all = [array1]
array2.forEach((i) => {
if (!arrayContainsSame(all, i)) {
all.push(i)
}
})
return all
}
function mergeConfigurations(rootConfig, additionalConfig) {
let copiedConfig = { rootConfig }
Object.keys(additionalConfig).forEach((key) => {
const doTypesMatch = propertyTypesDoMatch(copiedConfig[key], additionalConfig[key])
const propExistsInRoot = Object.hasOwnProperty.call(copiedConfig, key)
if (propExistsInRoot && isMergable(copiedConfig[key]) && doTypesMatch) {
if (Array.isArray(copiedConfig[key])) {
copiedConfig[key] = mergeArrays(copiedConfig[key], additionalConfig[key])
} else {
copiedConfig[key] = mergeConfigurations(copiedConfig[key], additionalConfig[key])
}
} else if (propExistsInRoot && doTypesMatch) {
copiedConfig[key] = additionalConfig[key]
} else {
copiedConfig = Object.assign(copiedConfig, { [key]: additionalConfig[key] })
}
})
return copiedConfig
}
var a = { a: 'oh', b: 'my', c: { a: 'a', b: { c: 'c' } } };
var b = { c: { b: { d: 'a' }, c: { d: 'd' } } };
var c = mergeConfigurations(a, b)
--enable-precise-memory-info
flag.
Test case name | Result |
---|---|
lodash | |
deepmerge | |
own impl |
Test name | Executions per second |
---|---|
lodash | 309929.2 Ops/sec |
deepmerge | 708380.6 Ops/sec |
own impl | 1251469.4 Ops/sec |
I'll explain the benchmarking setup and test cases in detail.
Benchmark Definition:
The benchmark measures the performance of three JavaScript libraries for merging objects:
lodash
: Lodash is a popular utility library that provides a wide range of functions for working with data, including object manipulation. The _merge
function is used to merge two or more objects into one.deepmerge
: Deepmerge is a lightweight library specifically designed for merging objects. It provides a simple and efficient way to merge objects without modifying the original objects.own impl
): This is the internal implementation of the merge logic, written by the developer.Test Cases:
The benchmark consists of three test cases:
lodash
: Tests the performance of Lodash's _merge
function with two example input objects.deepmerge
: Tests the performance of Deepmerge's merging function with two example input objects. The version used is 4.2.2.own impl
: Tests the performance of the custom implementation written by the developer, using the same example input objects as before.Options Compared:
The benchmark compares the performance of each library in terms of the number of executions per second (ExecutionsPerSecond).
Pros and Cons of Each Approach:
_merge
function):own impl
):Latest Benchmark Result:
The latest results show that:
own impl
) performs best, with an average of 744316 executions per second across all browsers and devices.Overall, the benchmark suggests that the custom implementation provides the best performance for object merging tasks, followed closely by Deepmerge.