1. Handwriting 62+ methods to learn the underlying principles of JavaScript
To determine whether an object has a circular reference has been included in handwriting various source code to achieve , you can also directly click isCyclic quickly view, there are currently 62+ handwritten implementations, welcome to learn together.
2. Need to talk about circular references
As shown in the figure below: I believe you have a similar problem before, 1617b40982278f circular reference. If two objects pass references to each other or the attribute references of the objects themselves may cause circular references.
In old browsers, circular references are a cause of memory leaks. Of course, with the improvement of garbage collection algorithms, circular references can now be handled well, which is no longer a problem.
only takes 3 minutes, this article will let you learn
- What situations may cause circular references ( important )?
- How to determine whether an object has a circular reference ( important )?
3. Several cases of circular references
There are two common circular references: objects refer to each other, and object refer to the object itself
3.1 Mutual references between objects
let obj1 = { name: '前端胖头鱼1' }
let obj2 = { name: '前端胖头鱼2' }
// 对象1的属性引用了对象2
obj1.obj = obj2
// 对象2的属性引用了对象1
obj2.obj = obj1
3.2 The properties of an object refer to the object itself
1. Directly refer to the outermost object
let obj = { name: '前端胖头鱼1' }
// 对象的属性引用了对象本身
obj.child = obj
2. Part of the attributes of the referenced object
let obj = {
name: '前端胖头鱼',
child: {}
}
obj.child.obj = obj.child
4. How to judge whether there is a circular reference in an object?
According to the possible situations of circular references, we can try to write the following code
4.1 Source code implementation
const isCyclic = (obj) => {
// 使用Set数据类型来存储已经检测过的对象
let stackSet = new Set()
let detected = false
const detect = (obj) => {
// 不是对象类型的话,可以直接跳过
if (obj && typeof obj != 'object') {
return
}
// 当要检查的对象已经存在于stackSet中时,表示存在循环引用
if (stackSet.has(obj)) {
return detected = true
}
// 将当前obj存如stackSet
stackSet.add(obj)
for (let key in obj) {
// 对obj下的属性进行挨个检测
if (obj.hasOwnProperty(key)) {
detect(obj[key])
}
}
// 平级检测完成之后,将当前对象删除,防止误判
/*
例如:对象的属性指向同一引用,如果不删除的话,会被认为是循环引用
let tempObj = {
name: '前端胖头鱼'
}
let obj4 = {
obj1: tempObj,
obj2: tempObj
}
*/
stackSet.delete(obj)
}
detect(obj)
return detected
}
4.2 Test one
// 1. 对象之间相互引用
let obj1 = { name: '前端胖头鱼1' }
let obj2 = { name: '前端胖头鱼2' }
// 对象1的属性引用了对象2
obj1.obj = obj2
// 对象2的属性引用了对象1
obj2.obj = obj1
console.log(isCyclic(obj1)) // true
console.log(isCyclic(obj2)) // true
// 2. 对象的属性引用了对象本身
let obj = { name: '前端胖头鱼1' }
// 对象的属性引用了对象本身
obj.child = obj
console.log(isCyclic(obj)) // true
// 3. 对象的属性引用部分属性
let obj3 = {
name: '前端胖头鱼',
child: {}
}
obj3.child.obj = obj3.child
console.log(isCyclic(obj3)) // true
// 4. 对象的属性指向同一引用
let tempObj = {
name: '前端胖头鱼'
}
let obj4 = {
obj1: tempObj,
obj2: tempObj
}
console.log(isCyclic(obj4)) // false
// 5. 其他数据类型
console.log(isCyclic(1)) // false
console.log(isCyclic('前端胖头鱼')) // false
console.log(isCyclic(false)) // false
console.log(isCyclic(null)) // false
console.log(isCyclic(undefined)) // false
console.log(isCyclic([])) // false
console.log(isCyclic(Symbol('前端胖头鱼'))) // false
5. End
A very small point of knowledge, thank you all for reading. If you are interested, you can further explore some interesting topics:
for example:
- How to output objects with circular references
JSON.stringify
- How to deal with circular references in the garbage collection mechanism of JS and so on.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。