art-standard-lib
Version:
The Standard Library for JavaScript that aught to be.
129 lines (105 loc) • 4.52 kB
text/coffeescript
{compactFlatten} = require "./ArrayCompactFlatten"
{isPlainObject} = require './Types'
module.exports = class Merge
###
merge "flattens" its args and then adds all keys from all objects in
the list into a new object which is returned.
return: new object
The first object's keys are added first. If two or more objects have the same
keys, the value set in the result is the last object's in the list with that key.
###
@merge: merge = (all...) -> mergeInto {}, all
@mergeWithoutNulls: (all...) -> mergeIntoWithNullDeletes {}, all
# New, better name
@mergeWith: (all...) ->
mergeInto {}, @, all
# ALIAS - DEPRECATE?
@mergeWithSelf: @mergeWith
###
The same as 'merge' with one difference:
Instead of a new object, all objects are merged into the first object in the list.
return: first object in the flattened list
return: null if no source objects
###
@mergeInto: mergeInto = (all...) ->
sources = compactFlatten all
return null if sources.length == 0
result = sources[0] || {}
for source in sources when source != result
result[k] = v for k, v of source when v != undefined
result
@mergeIntoWithNullDeletes: mergeIntoWithNullDeletes = (all...)->
sources = compactFlatten all
return null if sources.length == 0
result = sources[0] || {}
for source in sources when source != result
for k, v of source
switch
when v? then result[k] = v
when v == null then delete result[k]
result
###
Just like mergeInfo except only merge into the result object
UNLESS 'result' already has that property with a non-undefined value.
if
mergeInfo a, b is just like merge a, b except it modifies and returns a instead of returning a new object
then
mergeIntoUnless b, a is just like merge a, b except it modifies and returns b instead of returning a new object
Note: mergeIntoUnless a, b, c, d, e, f is like merge f, e, d, c, b, a
###
@mergeIntoUnless: (all...)->
sources = compactFlatten all
return null if sources.length == 0
result = sources[0] || {}
for i in [1...sources.length] by 1
source = sources[i]
for k, v of source when result[k] == undefined
result[k] = v
result
@deepMerge: deepMerge = (all...) ->
for k, v of out = merge array = compactFlatten all
if isPlainObject v
out[k] = _deepMerge (val[k] for val in array)
out
_deepMerge = (array) ->
for k, v of out = merge array = compactFlatten array
if isPlainObject v
out[k] = _deepMerge (val[k] for val in array)
out
# true if o2 has all the properties of o1 (possibly more, and possibly with different values including undefined or nul)
@hasAllProps: (o1, o2) ->
for k, v of o1
return false unless o2.hasOwnProperty k
true
# Like merge, it doesn't alter any of the inputs
# Unlike merge, it returns o2 without creating a new object if the result would be identical to o2.
# if o1 or o2 is null/undefined, return the other
# if both are unll/undefined, return o2
# the name "pureMerge" comes from pure-functional-merge - as in this is how you'd implement
# merge if you were asuming o1, o2 and the result of pureMerge were never modified.
# TODO: a better name may be leanMerge - since it is ligher weight than "merge".
@pureMerge: pureMerge = (all...)=>
sources = compactFlatten all
return null if sources.length == 0
return sources[0] if sources.length == 1
# only apply merge if the last object is missing a key from another object
last = sources[sources.length - 1]
for source in sources when source != last
return @merge sources unless @hasAllProps source, last
last
###
I might consider adding "o" - which works like Object-Tree constructors:
First, it compact-flattens args
Second, it gathers up and merges all plain-objects in its args list
Last, all remaining items get added to the "children" list
The question is, what does it return? Options:
OPTION: If only plain-objects after compact-flatten, just return the merged object ELSE:
Options if both objects and non-object values are present:
a. return compactFlatten [plainObject, nonObjectValues]
b. return merge plainObject, children: nonObjectValues
c. return new MClass plainObject, nonObjectValues
class MClass extends BaseObject
@properties "props children"
constructor: (@props, @children) ->
###
@m: pureMerge