Как понимать этот код, что здесь происходит?

Условие задачи:
В простых случаях циклических ссылок мы можем исключить свойство, из-за которого они возникают, из сериализации по его имени.

Но иногда мы не можем использовать имя, так как могут быть и другие, нужные, свойства с этим именем во вложенных объектах. Поэтому можно проверять свойство по значению.

Напишите функцию replacer для JSON-преобразования, которая удалит свойства, ссылающиеся на meetup


Решение:
let room = {
  number: 23
};
 
let meetup = {
  title: "Совещание",
  occupiedBy: [{name: "Иванов"}, {name: "Петров"}],
  place: room
};
 
room.occupiedBy = meetup;
meetup.self = meetup;
 
alert( JSON.stringify(meetup, function replacer(key, value) {
  return (key != "" && value == meetup) ? undefined : value;
}));
 

/*
{
  "title":"Совещание",
  "occupiedBy":[{"name":"Иванов"},{"name":"Петров"}],
  "place":{"number":23}
}
*/


Не понимаю сам принцип работы такого условия... Почему при ключе равном "" и значении value - не возвращаются другие свойства ссылающиеся на meetup?
  • Вопрос задан
  • 151 просмотр
Решения вопроса 1
alexey-m-ukolov
@alexey-m-ukolov Куратор тега JavaScript
Я не понимаю, что тут может остаться непонятным с предыдущего вашего вопроса.
Цель - избаваться от циклических ссылок, которые делают сериализацию объекта невозможной. При этом ориентироваться требуется не на название поля, а на его значение.
Именно это и происходит в функции replacer, с поправкой на то, что при первом вызове в replacer передаётся весь объект целиком с пустым ключом:
Initially, the replacer function is called with an empty string as key representing the object being stringified.
https://developer.mozilla.org/en-US/docs/Web/JavaS...

key != "" && value == meetup
Переводится как "если ключ не пуст (т.е. не первая итерация, в которой value ссылается на объект целиком) и значение равно искомому объекту, его нужно пропустить и не сериализовывать".
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
Alexandroppolus
@Alexandroppolus
кодир
Напишите функцию replacer для JSON-преобразования, которая удалит свойства, ссылающиеся на meetup


дурацкое условие.
почему удалять только ссылки на meetup? кольцевых ссылок может быть сколько угодно и каких угодно, например room.self = room;, могут быть и более длинные произвольные цепочки

в общем виде тут надо отслеживать, где мы находимся на каждом вызове реплейсера (иметь актуальную цепочку парентов), и по этой цепочке проверять, был ли такой объект, и если был, выкидывать.

код

function makeReplacer() {
    const path = [];

    return (k, v) => {
        // простое значение не записываем в путь
        if (!v || typeof v !== 'object') {
            return v;
        }

        // находим родительский объект; всё что глубже, выкидываем
        for (let i = path.length - 1; i >= 0; --i) {
            const item = path[i];
            if (Object.prototype.hasOwnProperty.call(item.obj, k) && item.obj[k] === v && !item.handled.has(k)) {
                item.handled.add(k);
                break;
            } else {
                path.pop();
            }
        }

        // если в парентах уже был текущий объект, то игнорируем его
        if (path.find((item) => item.obj === v)) {
            return undefined;
        }

        // записываем объект в путь и возвращаем
        path.push({
            obj: v,
            handled: new Set()
        });
        return v;
    };
}

// -----------------------------
// пример использования

let room = {
  number: 23
};

let obj1 = {a: {b: room, bb: 23}, c: 34};
 
let meetup = {
  title: "Совещание",
  occupiedBy: [room, {name: "Иванов"}, {name: "Петров"}],
  place: room
};
 
room.occupiedBy = meetup;
meetup.self = meetup;
room.self = room;
room.obj1 = obj1;

console.log(JSON.stringify(meetup, makeReplacer(), 4))

Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы