Разберите URLSearchParams, разделите ключи по точкам и создайте промежуточные объекты. Запретите опасные ключи и конфликт скалярного значения с вложенным объектом.
Преобразование параметров URL‑запроса в вложенный объект
Разберите URLSearchParams, разделите ключи по точкам и создайте промежуточные объекты. Запретите опасные ключи и конфликт скалярного значения с вложенным объектом.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Создайте функцию, принимающую строку запроса из URL и возвращающую её параметры в виде вложенного JavaScript‑объекта.
const rawQuery = "user.name.firstname=Bob&user.name.lastname=Smith&user.favoritecolor=Light%20Blue&experiments.theme=dark";
function buildQueryObject(str) {
// реализация
}
buildQueryObject(rawQuery);
/*
{
'user': {
'name': {
'firstname': 'Bob',
'lastname': 'Smith'
},
'favoritecolor': 'Light Blue'
},
experiments: {
theme:'dark'
}
}
*/
Ответ
Разберите URLSearchParams, разделите ключи по точкам и создайте промежуточные объекты. Запретите опасные ключи и конфликт скалярного значения с вложенным объектом.
function buildQueryObject(str) {
const result = Object.create(null);
for (const [key, value] of new URLSearchParams(str)) {
const parts = key.split('.');
if (parts.some(part => !part || ['__proto__', 'constructor', 'prototype'].includes(part))) {
throw new Error('Недопустимый путь');
}
let node = result;
for (let i = 0; i < parts.length - 1; i++) {
const part = parts[i];
if (!Object.hasOwn(node, part)) node[part] = Object.create(null);
if (typeof node[part] !== 'object' || node[part] === null) throw new Error('Конфликт пути');
node = node[part];
}
const last = parts[parts.length - 1];
if (Object.hasOwn(node, last) && typeof node[last] === 'object') throw new Error('Конфликт пути');
node[last] = value;
}
return result;
}
Декодирование %20 и плюсов выполняет URLSearchParams. Все значения остаются строками; повтор одинакового конечного ключа заменяется последним значением. Для внешнего ввода дополнительно ограничивают длину запроса и глубину пути.