I am paring two objects that contains values as string
, number
, array
and object
. To this point there is no problem. When I am trying to pare self-referenced objects I am getting the following error RangeError: Maximum call stack size exceeded
. Self-referenced objects should be considered equal if they are referenced to the same level of the other object. My question is how to implement it. Here is my code :
const equalsComplex = function(value, other) {
// Get the value type
const type = Object.prototype.toString.call(value);
// If the two objects are not the same type, return false
if (type !== Object.prototype.toString.call(other)) return false;
// If items are not an object or array, return false
if (['[object Array]', '[object Object]'].indexOf(type) < 0) return false;
// Compare the length of the length of the two items
const valueLen =
type === '[object Array]' ? value.length : Object.keys(value).length;
const otherLen =
type === '[object Array]' ? other.length : Object.keys(other).length;
if (valueLen !== otherLen) return false;
// Compare two items
const pare = function(item1, item2) {
// Get the object type
const itemType = Object.prototype.toString.call(item1);
// If an object or array, pare recursively
if (['[object Array]', '[object Object]'].indexOf(itemType) >= 0) {
if (!equalsComplex(item1, item2)) return false;
}
// Otherwise, do a simple parison
else {
// If the two items are not the same type, return false
if (itemType !== Object.prototype.toString.call(item2)) return false;
// Else if it's a function, convert to a string and pare
// Otherwise, just pare
if (itemType === '[object Function]') {
if (item1.toString() !== item2.toString()) return false;
} else {
if (item1 !== item2) return false;
}
}
};
// Compare properties
if (type === '[object Array]') {
for (let i = 0; i < valueLen; i++) {
if (pare(value[i], other[i]) === false) return false;
}
} else {
for (let key in value) {
if (value.hasOwnProperty(key)) {
if (pare(value[key], other[key]) === false) return false;
}
}
}
// If nothing failed, return true
return true;
};
const r = { a: 1 };
r.b = r;
const d = { a: 1 };
d.b = d;
console.log(
equalsComplex(
{
a: 2,
b: '2',
c: false,
g: [
{ a: { j: undefined } },
{ a: 2, b: '2', c: false, g: [{ a: { j: undefined } }] },
r
]
},
{
a: 2,
b: '2',
c: false,
g: [
{ a: { j: undefined } },
{ a: 2, b: '2', c: false, g: [{ a: { j: undefined } }] },
r
]
}
)
);
I am paring two objects that contains values as string
, number
, array
and object
. To this point there is no problem. When I am trying to pare self-referenced objects I am getting the following error RangeError: Maximum call stack size exceeded
. Self-referenced objects should be considered equal if they are referenced to the same level of the other object. My question is how to implement it. Here is my code :
const equalsComplex = function(value, other) {
// Get the value type
const type = Object.prototype.toString.call(value);
// If the two objects are not the same type, return false
if (type !== Object.prototype.toString.call(other)) return false;
// If items are not an object or array, return false
if (['[object Array]', '[object Object]'].indexOf(type) < 0) return false;
// Compare the length of the length of the two items
const valueLen =
type === '[object Array]' ? value.length : Object.keys(value).length;
const otherLen =
type === '[object Array]' ? other.length : Object.keys(other).length;
if (valueLen !== otherLen) return false;
// Compare two items
const pare = function(item1, item2) {
// Get the object type
const itemType = Object.prototype.toString.call(item1);
// If an object or array, pare recursively
if (['[object Array]', '[object Object]'].indexOf(itemType) >= 0) {
if (!equalsComplex(item1, item2)) return false;
}
// Otherwise, do a simple parison
else {
// If the two items are not the same type, return false
if (itemType !== Object.prototype.toString.call(item2)) return false;
// Else if it's a function, convert to a string and pare
// Otherwise, just pare
if (itemType === '[object Function]') {
if (item1.toString() !== item2.toString()) return false;
} else {
if (item1 !== item2) return false;
}
}
};
// Compare properties
if (type === '[object Array]') {
for (let i = 0; i < valueLen; i++) {
if (pare(value[i], other[i]) === false) return false;
}
} else {
for (let key in value) {
if (value.hasOwnProperty(key)) {
if (pare(value[key], other[key]) === false) return false;
}
}
}
// If nothing failed, return true
return true;
};
const r = { a: 1 };
r.b = r;
const d = { a: 1 };
d.b = d;
console.log(
equalsComplex(
{
a: 2,
b: '2',
c: false,
g: [
{ a: { j: undefined } },
{ a: 2, b: '2', c: false, g: [{ a: { j: undefined } }] },
r
]
},
{
a: 2,
b: '2',
c: false,
g: [
{ a: { j: undefined } },
{ a: 2, b: '2', c: false, g: [{ a: { j: undefined } }] },
r
]
}
)
);
Share
Improve this question
edited May 10, 2019 at 17:23
John John
asked May 8, 2019 at 19:55
John JohnJohn John
1,5004 gold badges23 silver badges45 bronze badges
12
- 1 You could send a Set along of values you already handled / verified? – Icepickle Commented May 8, 2019 at 20:01
- That will allow you to halt the infinite recursion, but will you be able to tell if the circular object is at the same place in both arguments? – Barmar Commented May 8, 2019 at 20:02
- @Icepickle I don't quite get it – John John Commented May 8, 2019 at 20:02
-
this answer claims that the
_.isEqual()
function in underscore.js will do this. However, the documentation doesn't say so. – Barmar Commented May 8, 2019 at 20:04 - @Barmar I haven't read that much of the question yet