HTML Preparation code:
x
 
1
<script src='https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.min.js'></script>
2
3
<script src='https://unpkg.com/deepmerge@4.2.2/dist/umd.js'></script>
Script Preparation code:
 
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);
Tests:
  • lodash

     
    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);
  • deepmerge

     
    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);
  • own impl

     
    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)
Rendered benchmark preparation results:

Suite status: <idle, ready to run>

Previous results

Experimental features:

  • Test case name Result
    lodash
    deepmerge
    own impl

    Fastest: N/A

    Slowest: N/A

Latest run results:
Run details: (Test run date: 13 days ago)
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36
Chrome 135 on Windows
View result in a separate tab
Test name Executions per second
lodash 309929.2 Ops/sec
deepmerge 708380.6 Ops/sec
own impl 1251469.4 Ops/sec