Настройки интернет-банка Альфы собираются из трёх слоёв: значения по умолчанию, настройки сегмента (премиум, бизнес) и то, что клиент поменял сам. Каждый следующий слой важнее предыдущего.
Напишите deepMerge(...sources). Результат — новый объект. Если в двух слоях по ключу лежат обычные объекты, они сливаются рекурсивно. Во всех остальных случаях значение позднего слоя заменяет раннее: массивы не склеиваются, а заменяются копией.
Значение undefined в позднем слое ничего не меняет, null — перезаписывает. Входные объекты не меняются: изменение результата не должно затронуть настройки по умолчанию.
Слои приходят из JSON от сервера, поэтому ключи __proto__, constructor и prototype пропускаются: иначе {"__proto__": {"isAdmin": true}} допишет поле всем объектам страницы.
В работе: Клиент выключил пуш о списаниях до 100 ₽, а сегмент «Премиум» добавил лимит переводов 3 млн ₽ — оба изменения должны дожить до экрана.
Пример 1: три слоя настроек
[{"theme": "light", "notify": {"push": true, "sms": true, "minAmount": 0}, "limits": {"transfer": 1000000}}, {"limits": {"transfer": 3000000, "cash": 500000}}, {"notify": {"minAmount": 100}, "theme": "dark"}], null{"result": {"theme": "dark", "notify": {"push": true, "sms": true, "minAmount": 100}, "limits": {"transfer": 3000000, "cash": 500000}}, "inputsIntact": true, "polluted": false}Пример 2: массив заменяется, а не склеивается
[{"widgets": ["cards", "deposits", "cashback"]}, {"widgets": ["cashback"]}], null{"result": {"widgets": ["cashback"]}, "inputsIntact": true, "polluted": false}deepMerge — тест вызывает её сам. Таймеры и Date в тестах ненастоящие: время идёт по команде теста, поэтому setTimeout на 5 секунд проверяется мгновенно. Тестов 9: 2 открыты выше, остальные приходят после старта подхода. Лимит — 2 с на тест.
function deepMerge(...sources) // → object
Источник: на задачах Альфа-Банка: настройки интернет-банка. Условие пересказано своими словами.
Ожидаемый ответ не нужен: покажем, что вернула функция.
Здесь появится результат отправки.