Note that a = [ v = 1 ]
is an array, not an object. It's the same as v = 1; a = [ v ]
, which boils down to a = [ 1 ]
, and if you want to read the first value you have to write a[0]
. However, since your merging strategy is "based on the name of objects", it seems more appropriate to use a dictionary d = { v : 1 }
. In this case, you can get the value by its name with d["v"]
.
In the JavaScript world, people use the word "object" rather than "dictionary". No matter the word, what you need to remember is that objects and arrays are different since they inherit from different classes. Indeed, {}
means new Object()
, while []
means new Array()
. Also, most of the time people enumerate the properties of an object with a for ... in
loop, and iterate over the elements of an array either with a for ... of
loop or with a for
loop. Again, knowing that you are interested in the name of objects, the for ... in
loop is probably the best option for you.
That being said, despite of our discussion in the comments, it's still not perfectly clear to me what you are trying to achieve. Hence, I've decided to write a generic merging function. This function is able to merge any type of objects.1 Here is a couple of use cases :
> | merge("azerty", null) // b wins
< | null
> | merge("azerty", { t : true }) // b wins
< | { t : true }
> | merge({ t : true }, "azerty") // b wins
< | "azerty"
> | merge([1, 2, 3], [undefined, 5]) // a[0] wins, b[1] wins
< | [1, 5, 3]
> | merge("azerty", undefined) // a wins
< | "azerty"
The merging strategy is dead simple and can be summarized as follows :
If a
is an array and b
is an array, or if a
is a dictionary and b
is a dictionary, then merge them recursively, otherwise, b
always wins unless it's undefined
.
main({
m : [ 1, { ms : "ms", mf : false }, 3 ],
n : { ns : "ns", na : [ null, undefined ] },
o : { os : "os" }
}, {
m : [ -1, { mt : true } ],
n : { nt : true, na : [ undefined, null ] }
});
function merge (a, b) {
if (isFunction(b)) {
return b;
} else if (isArray(b)) {
if (!isArray(a)) {
return b;
} else {
var max = Math.max(
a.length, b.length
);
for (var i = 0; i < max; i++) {
b[i] = merge(a[i], b[i]);
}
return b;
}
} else if (isComplex(b)) {
if (!isComplex(a) || isArray(a) || isFunction(a)) {
return b;
} else {
for (var k in a) {
b[k] = merge(a[k], b[k]);
}
return b;
}
} else if (b === undefined) {
if (isFunction(a)) {
return a;
} else if (isArray(a)) {
return merge(a, []);
} else if (isComplex(a)) {
return merge(a, {});
} else {
return a;
}
} else {
return b;
}
}
function main (a, b) {
var pre = document.getElementsByTagName("pre");
b = merge(a, b);
pre[0].textContent = "a = " + (
fixUndef(JSON.stringify(a, markUndef, 2))
);
pre[1].textContent = "b = " + (
fixUndef(JSON.stringify(b, markUndef, 2))
);
}
function isComplex (x) {
return x === Object(x);
}
function isArray (x) {
return x instanceof Array;
}
function isFunction (x) {
return typeof x === "function";
}
// JSON.stringify() replaces
// `undefined` with `null`, the
// below functions are meant to
// fix this behavior.
function markUndef (k, v) {
return v === undefined ? "UNDEF" : v;
}
function fixUndef (s) {
return s.replace("\"UNDEF\"", "undefined");
}
pre {
display : inline-block;
vertical-align: top;
width: 50%;
}
<pre></pre><pre></pre>
1 I leave it to you to prove the algorithm correctness before using this function :-P