Опыт интервью, который сделал меня таким грустным.
Недавно моя подруга потеряла вакансию, которую ей очень нравилась, просто потому, что она не знала, как определить, является ли переменная объектом циклической ссылки.
Что меня разозлило, так это то, что интервьюер бесцеремонно сказал ей после окончания: "Ваша основа Javascript слишком плоха, вам не нужно продолжать интервью позже".
Какое ужасное интервью…
1. TypeError: циклическое значение объекта
Друзья мои, возможно вы сталкивались с такой ошибкой, она не чужда фронтенд-разработчику.
Исключение JavaScript «циклическое значение объекта» возникает, когда ссылки на объекты находятся в JSON. JSON.stringify() не пытается их решить и соответственно терпит неудачу.
2. 3 примера объектов с циклическими ссылками
Когда вы используете функцию JSON.stringify(obj)
, убедитесь, что obj
не является объектом с циклической ссылкой, иначе будет выдано исключение.
На самом деле существует как минимум три способа заставить объект иметь циклическую ссылку.
- Два объекта ссылаются друг на друга
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
- Свойства объекта являются его собственными
let obj = { name: 'fatfish1' } // The value of child is obj obj.child = obj
- Свойства объекта являются частью его свойств
let obj = { name: 'fatfish', child: { age: 100 } } obj.child.obj = obj.child
3. Циклический
После приведенного выше анализа давайте попробуем реализовать функцию, функция которой состоит в том, чтобы судить, является ли объект круговым эталонным объектом.
// 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 }
Пройти тест
// 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
Отлично, isCyclic проходит все тесты.
4. Используйте более безопасный json-цикл
Наконец, вы можете использовать json-cycle для решения возможных проблем с циклическими ссылками.
var jc = require('json-cycle'); var a = {}; a.self = a; console.log(JSON.stringify(jc.decycle(a))); // {{"$ref":"$"}}
Дополнительные материалы на PlainEnglish.io. Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Присоединяйтесь к нашему сообществу Discord и следите за нами в Twitter, LinkedIn и YouTube.
Узнайте, как привлечь внимание к своему стартапу с помощью Circuit.