I Lost a Job Opportunity Just Because of “cyclic object value”
An interview experience that made me so sad.

Recently, my friend lost a job opportunity she cherished simply because she didn’t know how to determine if a variable was a circular reference object.
What made me angry was that the interviewer said to her unceremoniously after the end: “Your Javascript foundation is too poor, you don’t need to continue the interview later.”
What a terrible interview experience…
1. TypeError: cyclic object value
My friends, maybe you have encountered such an error, it is not unfamiliar to a front-end development engineer.

The JavaScript exception “cyclic object value” occurs when object references are found in JSON. JSON.stringify() doesn’t try to solve them and fails accordingly.
2. 3 examples of objects with circular references
When you use the JSON.stringify(obj) function, make sure that obj is not a circularly referenced object, otherwise, it will throw an exception.
In fact, there are at least three ways to cause an object to have a circular reference.
- Two objects refer to each other
let obj1 = { name: 'fatfish1' }
let obj2 = { name: 'fatfish2' }
// The properties of object 1 refer to object 2
obj1.obj = obj2
// The properties of object 2 refer to object 1
obj2.obj = obj1
- The properties of an object are its own
let obj = { name: 'fatfish1' }
// The value of child is obj
obj.child = obj
- An object’s properties are part of its properties
let obj = {
name: 'fatfish',
child: {
age: 100
}
}obj.child.obj = obj.child
3. isCyclic
After the above analysis, let us try to implement a function whose function is to judge whether an object is a circular reference object.
// Check if an object has a circular reference
const isCyclic = (obj) => {
// Use the Set data type to store detected objects
let stackSet = new Set()
let detected = false const detect = (obj) => {
// If it is not an object type, you can skip it directly
if (obj && typeof obj != 'object') {
return
}
// When the object to be checked already exists in the stackSet, it means that there is a circular reference
if (stackSet.has(obj)) {
return detected = true
}
// Save the current obj as a stackSet
stackSet.add(obj)
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
detect(obj[key])
}
}
// After the level detection is completed, delete the current object to prevent misjudgment
/*
For example:
an object's attribute points to the same reference.
If it is not deleted, it will be regarded as a circular reference
let tempObj = {
name: 'fatfish'
}
let obj4 = {
obj1: tempObj,
obj2: tempObj
}
*/
stackSet.delete(obj)
}
detect(obj)
return detected
}Have a test
// 1. Two objects refer to each other
let obj1 = { name: 'fatfish1' }
let obj2 = { name: 'fatfish2' }
// The properties of object 1 refer to object 2
obj1.obj = obj2
// The properties of object 2 refer to object 1
obj2.obj = obj1
console.log(isCyclic(obj1)) // true
console.log(isCyclic(obj2)) // true
// 2. The properties of an object are its own
let obj = { name: 'fatfish1' }
// The value of child is obj
obj.child = obj
console.log(isCyclic(obj)) // true
// 3. An object's properties are part of its properties
let obj = {
name: 'fatfish',
child: {
age: 100
}
}
obj3.child.obj = obj3.child
console.log(isCyclic(obj3)) // true
// 4. A property of an object points to the same object
let tempObj = {
name: 'fatfish'
}
let obj4 = {
obj1: tempObj,
obj2: tempObj
}
console.log(isCyclic(obj4)) // false
// 5. other data types
console.log(isCyclic(1)) // false
console.log(isCyclic('fatfish')) // false
console.log(isCyclic(false)) // false
console.log(isCyclic(null)) // false
console.log(isCyclic(undefined)) // false
console.log(isCyclic([])) // false
console.log(isCyclic(Symbol('fatfish'))) // falseGreat, isCyclic passes all the tests.
4. Use the safer json-cycle
Finally, you can use json-cycle to solve possible circular reference problems.
var jc = require('json-cycle');
var a = {};
a.self = a;
console.log(JSON.stringify(jc.decycle(a))); // {{"$ref":"$"}}





