avatarfatfish

Summary

The article discusses the experience of an individual who lost a job opportunity due to a lack of understanding of circular references in JavaScript, and it provides an in-depth explanation of how to detect such references using a custom isCyclic function, as well as a solution using the json-cycle library.

Abstract

The author recounts a distressing interview experience where a candidate was rejected for not knowing how to handle circular object references in JavaScript, which are problematic when using JSON.stringify(). The article explains the concept of circular references with examples, such as two objects referencing each other, an object referencing itself, or an object's property referencing part of itself. To address this, the author presents a detailed implementation of the isCyclic function, which uses a Set to track objects and detect circular references. The function is demonstrated with various test cases, confirming its effectiveness. Additionally, the article suggests using the json-cycle library as a safer alternative to handle JSON stringification of objects with circular references.

Opinions

  • The author expresses frustration and disappointment with the interviewer's approach, highlighting the importance of constructive feedback over blunt criticism.
  • There is an underlying tone of advocacy for a deeper understanding of JavaScript foundations, particularly for front-end development roles.
  • The article conveys a didactic intent, aiming to educate readers on a specific JavaScript challenge and providing a practical solution.
  • The author emphasizes the practicality of the isCyclic function and the json-cycle library, suggesting that familiarity with such tools can prevent similar interview mishaps.

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.

  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
  1. The properties of an object are its own
let obj = { name: 'fatfish1' }
// The value of child is obj
obj.child = obj
  1. 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'))) // false

Great, 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":"$"}}
Front End Development
JavaScript
React
Angular
Nodejs
Recommended from ReadMedium