I have written a function that is designed to convert an object into an array of key/pair values ("flattening it") like so:
Input
{
"a": true,
"b": {
"c": 500
}
}
Output
[
["a", true],
["b", [
["c", 500]
]
]
Here is the code I have written to do it:
function isCyclicObject(object, seenObjects) {
seenObjects = (seenObjects instanceof Array) ? seenObjects : [];
if (object instanceof Object) {
if (seenObjects.indexOf(object) !== -1) {
return true;
}
seenObjects.push(object);
for (var key in object) {
if (object.hasOwnProperty(key) && isCyclicObject(object[key], seenObjects)) {
return true;
}
}
return false;
}
return false;
}
function flattenObject(object) {
if (!(object instanceof Object) || isCyclicObject(object)) {
return null;
}
var flattened = [];
for (var key in object) {
var value = object[key];
if (value instanceof Object) {
value = flattenObject(value);
if (value === null) {
return null;
}
}
flattened.push([key, value]);
}
return flattened;
}
I don't really have any major concerns over my code, however I would really appreciate having someone review it and point out any mistakes or flaws in my code that I haven't noticed. I'm also not all too familiar with how to lay out my JS code, so I believe that could possibly be improved too.
And here is the code I wrote to test its functionality:
function compareArrays(first, second) {
if (!(first instanceof Array) || !(second instanceof Array)) {
return false;
}
if (first.length != second.length) {
return false;
}
for (var i = 0; i < first.length; i++) {
var firstValue = first[i],
secondValue = second[i];
if (firstValue instanceof Array && secondValue instanceof Array) {
if (!compareArrays(firstValue, secondValue)) {
return false;
}
} else if (firstValue != secondValue) {
return false;
}
}
return true;
}
function testFlattenObject(object, expected) {
var flattened = flattenObject(object);
var objectString = JSON.stringify(object),
expectedString = JSON.stringify(expected),
flattenedString = JSON.stringify(flattened);
var failed = false;
if (object instanceof Object) {
failed = !compareArrays(flattened, expected);
} else {
failed = flattened !== null;
}
if (failed) {
console.error("Test failed for " + objectString + ": expected " + expectedString + " but got " + flattenedString);
} else {
console.log("Test passed");
}
}
testFlattenObject({}, []);
testFlattenObject({
a: true
}, [
["a", true]
]);
testFlattenObject({
a: true,
b: {
c: 500
}
}, [
["a", true],
["b", [
["c", 500]
]]
]);
isCyclicObject
function returns false positives for references to the same substructure. Take for examplevar z = {}; isCyclicObject({ a: z. b: z })
. This happens because you're not popping anything offseenObjects
. \$\endgroup\$