Merge
Merge and extend objects.
Installation
$ npm install utils-merge2
For use in the browser, use browserify.
Usage
var createMergeFcn = require( 'utils-merge2' );
createMergeFcn( [options] )
Returns a function
for merging and extending objects
.
var merge = createMergeFcn();
The function
accepts the following options
:
-
level: limits the merge depth. The default merge strategy is a deep (recursive) merge. Default: level = Number.POSITIVE_INFINITY
.
var merge = createMergeFcn({
'level': 2
});
-
copy: boolean
indicating whether to deep copy merged values. Deep copying prevents shared references and source object
mutation. Default: true
.
var merge = createMergeFcn({
'copy': false
});
-
override: defines the merge strategy. If true
, source object
values will always override target object
values. If false
, source values never override target values (useful for adding, but not overwriting, properties). To define a custom merge strategy, provide a function
. Default: true
.
var merge = createMergeFcn({
'override': false
});
function strategy( a, b, key ) {
return <something>;
}
merge = createMergeFcn({
'override': strategy
});
-
extend: boolean
indicating whether new properties can be added to the target object
. If false
, only shared properties are merged. Default: true
.
var merge = createMergeFcn({
'extend': false
});
merge( target, source1[, source2[,...,sourceN]] )
Merge and extend a target object
.
var target, source, out;
target = {
'a': 'beep'
};
source = {
'a': 'boop',
'b': 'bap'
};
out = merge( target, source );
The function
accepts multiple source objects
.
var target, source1, source2, out;
target = {
'a': 'beep'
};
source1 = {
'b': 'boop'
};
source2 = {
'c': 'cat'
};
out = merge( target, source1, source2 );
Notes
-
The target object
is mutated.
var target, source, out;
target = {
'a': 'beep'
};
source = {
'b': 'boop'
};
out = merge( target, source );
console.log( out === target );
console.log( target.b );
To return a new object
, provide an empty object
as the first argument.
var target, source, out;
target = {
'a': 'beep'
};
source = {
'b': 'boop'
};
out = merge( {}, target, source );
console.log( out === target );
-
The default merge is a deep (recursive) merge. Hence,
var target, source, out;
target = {
'a': {
'b': {
'c': 5
},
'd': 'beep'
}
};
source = {
'a': {
'b': {
'c': 10
}
}
};
out = merge( target, source );
-
By default, merged values are deep copied. Hence,
var target, source, out;
target = {
'a': null
};
source = {
'a': {
'b': [ 1, 2, 3 ]
}
};
merge( target, source );
console.log( target.a.b === source.a.b );
-
Only plain JavaScript objects
are merged and extended. The following values/types are either deep copied or assigned:
Boolean
String
Number
Date
RegExp
Array
Int8Array
Uint8Array
Uint8ClampedArray
Init16Array
Uint16Array
Int32Array
Uint32Array
Float32Array
Float64Array
Buffer
(Node.js)
-
Deep copying does not work for the following values/types (see utils-copy):
Set
Map
Error
URIError
ReferenceError
SyntaxError
RangeError
If you need support for any of the above types, feel free to file an issue or submit a pull request.
-
Number
, String
, or Boolean
objects are merged as primitives.
-
functions
are not deep copied.
-
Support for deep merging class instances is inherently fragile.
-
Re: why this implementation and not the many other merge/xtend/node-extend/deep-merge/deep-extend modules out there.
- They always extend and merge and do not allow one or the other.
- They do not deep merge.
- They do not allow limiting the merge depth.
- If they deep copy, they fail to account for
Number
, String
, Boolean
, Buffer
, and typed array
objects, as well as class instances. - They do not allow custom merging strategies.
- They fail to validate options and arguments.
Examples
var createMergeFcn = require( 'utils-merge2' ),
createCopy = require( 'utils-copy' );
var source,
merge,
obj,
out;
obj = {
'a': 'beep',
'b': 'boop',
'c': {
'c1': 'woot',
'c2': false,
'c3': {
'c3a': [ 1, 2 ],
'c3b': null
}
},
'd': [ 1, 2, 3 ]
};
source = {
'b': Math.PI,
'c': {
'c1': 'bap',
'c3': {
'c3b': 5,
'c3c': 'bop'
},
'c4': 1337,
'c5': new Date()
},
'd': [ 4, 5, 6 ],
'e': true
};
merge = createMergeFcn();
out = merge( {}, obj, source );
merge = createMergeFcn({
'level': 2
});
out = merge( createCopy( obj ), createCopy( source ) );
merge = createMergeFcn({
'extend': false
});
out = merge( createCopy( obj ), source );
merge = createMergeFcn({
'override': false
});
out = merge( {}, obj, source );
merge = createMergeFcn({
'override': false,
'extend': false
});
out = merge( createCopy( obj ), source );
function strategy( a, b, key ) {
if ( typeof a === 'string' && typeof b === 'string' ) {
return a + b;
}
if ( Array.isArray( a ) && Array.isArray( b ) ) {
return a.concat( b );
}
if ( key === 'c3b' ) {
return b * 5000;
}
return a;
}
merge = createMergeFcn({
'override': strategy
});
out = merge( {}, obj, source );
function Foo( bar ) {
this._bar = bar;
return this;
}
merge = createMergeFcn();
obj = {
'time': new Date(),
'regex': /beep/,
'buffer': new Buffer( 'beep' ),
'Boolean': new Boolean( true ),
'String': new String( 'woot' ),
'Number': new Number( 5 ),
'Uint8Array': new Uint8Array( 10 ),
'Foo': new Foo( 'beep' )
};
source = {
'time': new Date( obj.time - 60000 ),
'regex': /boop/,
'buffer': new Buffer( 'boop' ),
'Boolean': new Boolean( false ),
'String': new String( 'bop' ),
'Number': new Number( 10 ),
'Uint8Array': new Uint8Array( 5 ),
'Foo': new Foo( 'boop' )
};
out = merge( obj, source );
To run the example code from the top-level application directory,
$ node ./examples/index.js
Tests
Unit
Unit tests use the Mocha test framework with Chai assertions. To run the tests, execute the following command in the top-level application directory:
$ make test
All new feature development should have corresponding unit tests to validate correct functionality.
Test Coverage
This repository uses Istanbul as its code coverage tool. To generate a test coverage report, execute the following command in the top-level application directory:
$ make test-cov
Istanbul creates a ./reports/coverage
directory. To access an HTML version of the report,
$ make view-cov
License
MIT license.
Copyright
Copyright © 2015. Athan Reines.