Toggle navigation
MeasureThat.net
Create a benchmark
Tools
Feedback
FAQ
Register
Log In
Run results for:
lodash merge vs deepmerge vs deepmerge-ts vs @fastify/deepmerge vs just-extend (take 3)
Go to the benchmark
Embed
Embed Benchmark Result
Run details:
User agent:
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36
Browser:
Chrome 133
Operating system:
Mac OS X 10.15.7
Device Platform:
Desktop
Date tested:
one year ago
Test name
Executions per second
lodash merge
234947.8 Ops/sec
deepmerge
799376.2 Ops/sec
deepmerge-ts
310591.3 Ops/sec
fastify deepmerge
3805904.2 Ops/sec
fastify deepmerge, with 'all: true'
777453.9 Ops/sec
just-extend
212391.2 Ops/sec
HTML Preparation code:
<script src='https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js'></script> <script src='https://unpkg.com/deepmerge@4.3.1/dist/umd.js'></script> <script type="module"> import { deepmerge } from 'https://unpkg.com/deepmerge-ts@5.1.0/dist/node/index.mjs'; window.deepmergeTs = deepmerge; </script> <script type="module"> import extend from 'https://unpkg.com/just-extend@6.2.0/index.mjs'; window.justExtend = extend; </script> <script type="module"> // CJS only :( // https://unpkg.com/browse/@fastify/deepmerge@1.3.0/ const JSON_PROTO = Object.getPrototypeOf({}) function deepmergeConstructor (options) { function isNotPrototypeKey (value) { return ( value !== 'constructor' && value !== 'prototype' && value !== '__proto__' ) } function cloneArray (value) { let i = 0 const il = value.length const result = new Array(il) for (i = 0; i < il; ++i) { result[i] = clone(value[i]) } return result } function cloneObject (target) { const result = {} if (cloneProtoObject && Object.getPrototypeOf(target) !== JSON_PROTO) { return cloneProtoObject(target) } const targetKeys = getKeys(target) let i, il, key for (i = 0, il = targetKeys.length; i < il; ++i) { isNotPrototypeKey(key = targetKeys[i]) && (result[key] = clone(target[key])) } return result } function concatArrays (target, source) { const tl = target.length const sl = source.length let i = 0 const result = new Array(tl + sl) for (i = 0; i < tl; ++i) { result[i] = clone(target[i]) } for (i = 0; i < sl; ++i) { result[i + tl] = clone(source[i]) } return result } const propertyIsEnumerable = Object.prototype.propertyIsEnumerable function getSymbolsAndKeys (value) { const result = Object.keys(value) const keys = Object.getOwnPropertySymbols(value) for (let i = 0, il = keys.length; i < il; ++i) { propertyIsEnumerable.call(value, keys[i]) && result.push(keys[i]) } return result } const getKeys = options && options.symbols ? getSymbolsAndKeys : Object.keys const cloneProtoObject = typeof options?.cloneProtoObject === 'function' ? options.cloneProtoObject : undefined function isMergeableObject (value) { return typeof value === 'object' && value !== null && !(value instanceof RegExp) && !(value instanceof Date) } function isPrimitive (value) { return typeof value !== 'object' || value === null } const isPrimitiveOrBuiltIn = typeof Buffer !== 'undefined' ? (value) => typeof value !== 'object' || value === null || value instanceof RegExp || value instanceof Date || value instanceof Buffer : (value) => typeof value !== 'object' || value === null || value instanceof RegExp || value instanceof Date const mergeArray = options && typeof options.mergeArray === 'function' ? options.mergeArray({ clone, deepmerge: _deepmerge, getKeys, isMergeableObject }) : concatArrays function clone (entry) { return isMergeableObject(entry) ? Array.isArray(entry) ? cloneArray(entry) : cloneObject(entry) : entry } function mergeObject (target, source) { const result = {} const targetKeys = getKeys(target) const sourceKeys = getKeys(source) let i, il, key for (i = 0, il = targetKeys.length; i < il; ++i) { isNotPrototypeKey(key = targetKeys[i]) && (sourceKeys.indexOf(key) === -1) && (result[key] = clone(target[key])) } for (i = 0, il = sourceKeys.length; i < il; ++i) { isNotPrototypeKey(key = sourceKeys[i]) && ( key in target && (targetKeys.indexOf(key) !== -1 && (result[key] = _deepmerge(target[key], source[key])), true) || // eslint-disable-line no-mixed-operators (result[key] = clone(source[key])) ) } return result } function _deepmerge (target, source) { const sourceIsArray = Array.isArray(source) const targetIsArray = Array.isArray(target) if (isPrimitive(source)) { return source } else if (isPrimitiveOrBuiltIn(target)) { return clone(source) } else if (sourceIsArray && targetIsArray) { return mergeArray(target, source) } else if (sourceIsArray !== targetIsArray) { return clone(source) } else { return mergeObject(target, source) } } function _deepmergeAll () { switch (arguments.length) { case 0: return {} case 1: return clone(arguments[0]) case 2: return _deepmerge(arguments[0], arguments[1]) } let result for (let i = 0, il = arguments.length; i < il; ++i) { result = _deepmerge(result, arguments[i]) } return result } return options && options.all ? _deepmergeAll : _deepmerge } window.deepmergeFastify = deepmergeConstructor </script>
Script Preparation code:
const a = { a: 'oh', b: 'my', c: { a: 'a', b: { c: 'c' } } }; const b = { c: { b: { d: 'a' }, c: { d: 'd' } } }; const c = { foo: { bar: 3 }, array: [{ does: 'work', too: [ 1, 2, 3 ] }] } const d = { foo: { baz: 4 }, quux: 5, array: [{ does: 'work', too: [ 4, 5, 6 ] }, { really: 'yes' }] } const objects = { a, b, c, d } window.OBJECTS = objects;
Tests:
lodash merge
const one = _.merge({}, OBJECTS.a, OBJECTS.b); const two = _.merge({}, OBJECTS.c, OBJECTS.d);
deepmerge
const one = deepmerge({}, OBJECTS.a, OBJECTS.b); const two = deepmerge({}, OBJECTS.c, OBJECTS.d);
deepmerge-ts
const one = deepmergeTs({}, OBJECTS.a, OBJECTS.b); const two = deepmergeTs({}, OBJECTS.c, OBJECTS.d);
fastify deepmerge
const _merge = deepmergeFastify(); const one = deepmergeFastify({}, OBJECTS.a, OBJECTS.b); const two = deepmergeFastify({}, OBJECTS.c, OBJECTS.d);
fastify deepmerge, with 'all: true'
const _merge = deepmergeFastify({ all: true }); const one = _merge({}, OBJECTS.a, OBJECTS.b); const two = _merge({}, OBJECTS.c, OBJECTS.d);
just-extend
const one = justExtend(true, {}, OBJECTS.a, OBJECTS.b); const two = justExtend(true, {}, OBJECTS.c, OBJECTS.d);