Skip to content

Instantly share code, notes, and snippets.

@jt3k
Created January 29, 2016 18:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jt3k/359fbf95588979789760 to your computer and use it in GitHub Desktop.
Save jt3k/359fbf95588979789760 to your computer and use it in GitHub Desktop.
/**
* Рекурсивная функция декомпозирующая объект.
* Обязательный только первый аргумент остальные нужны только для работы данной функции: TODO спрятать в arguments
* @param {Object} obj Приходящий в рекурсию объект(либо другое)
*
* @param {String} key Ключ по которому пришли
* @param {String} curPath Путь к ключу в текстовом виде
* @param {Number} deep Глубина рекурсии (глубина пути)
* @param {Object} returnObj Объект в который будет набиваться свойствами(см ниже),
* а также этот объект будет возвращён из данной функции
* @param {Object} upperObj Объект-родитель
*
*
* @return {Object} Объект вида
* {
* '#/путь/к/ключу/в/текстовом/виде': {
* value: 'значение_по_данному_пути', //может быть любым типом данных из объекта
* key: 'имя_ключа',
* deep: 9, //глубина пути,
* curPath: '#/путь/к/ключу/в/текстовом/виде',
* upperObj: {ссылка_на_объект_выше}
* },
* ...
* }
*/
function decomposer(obj, key, curPath, deep, returnObj, upperObj) {
// текущий путь
if (curPath) {
curPath += '/' + key;
} else {
curPath = key || '#';
}
// текущая глубина
if (deep) {
deep += 1;
} else {
deep = 1;
}
//входной объект
returnObj = returnObj || {};
// рекурсия тут
if (_.isObject(obj)) {
_.each(obj, function(value, key) {
decomposer(value, key, curPath, deep, returnObj, obj);
});
}
// curPath = curPath.replace(/^#\./,'#');
returnObj[curPath] = {
value: obj,
key: key,
deep: deep,
curPath: curPath,
upperObj: upperObj
};
if (deep === 1) {
return returnObj;
}
}
///////////////////////////////////////|||||||||||||||||\\\\\\\\\\\\\\\\\\\\
// пример использования
// Допустим нам необходимо делать разные действия с объектом, но мы не знаем где какое свойство лежит и как до него добраться
// Вот примерные кейсы которые с этой функцией возможны:
// 1) найти все места у которых есть свойство foo и добавить рядом свойство _newProp
// 2) найти все свойства со значением 123 и удалить весь объект в котором это свойство есть или любого из их родителей (например 2 родителя вверх или 99)
// 3) да в объем то и всё :) но этого достаточно чтобы делать всё что захочется.
// см примеры ниже в комментариях.
// берём объект без циклических ссылок.
var obj = {
foo: 123,
bar: 'lalala',
baz: {
fuz: {
biz: {
foo: 'bar in foo!'
}
}
}
};
//декомпозируем объект
var decomposedObj = decomposer(obj);
var foos = _.filter(decomposedObj, { key: 'foo'});
console.log(foos); // ==> вернёт 2 элемента с которыми можно делать ВСЁ %) ---> см в консоль (и действуй)
// ПОЛУЧИТЬ ТОЛЬКО ЗНАЧЕНИЯ СВОЙСТВ:
// _.map(foos, function(item){ return item.value});
// ДОБАВИТЬ НОВЫЕ СВОЙСТВА В ОБЪЕКТ:
// _.each(foos, function(item){ item.upperObj._newProp = 'lalala';})
// console.log(obj); ==> новые свойства добавлены в объектик.
// ДОБАВИТЬ НОВЫЕ СВОЙСВА В ОБЪЕКТ на два уровня выше
// // мы делаем .curPath = "#/baz/fuz/biz/foo" ==> "#/baz/fuz"
// var newPath = foos[1].curPath.split('/').slice(0, -2).join('/');
// var twoLevelUpObj = decomposedObj[newPath];
// twoLevelUpObj.upperObj._newProp2 = 'YOHOHO';
// // теперь наш obj будет содержать свойство baz.newProp2 = 'YOHOHO'
// почти таким способом мы можем сделать delete любому объекту из цепочки родителей.
//////////////////////////////////
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment