Сравнение двух обьектов. Поиск вложенного объекта в объекте

От сервера приходит два вида объекта, я хочу их сверить и дать какое-то тип для них.

const obj1 = {1: 'Что-то', 3: 'что-то еще', 89: '...'};
const obj2 = {
  0: {
    1: {},
    2: {},
    3: {}
  }
};

Скажем, если пришел объект вида obj1 нам нужно в этот объект добавить тип какое-то. Ну, чтобы их отличать. Так же и для obj2 если нам пришел такой вид объекта.

Пример, что я хочу получить на выходе.

// Проверяем, если у нас объект обычный, даем тип и возвращаем объект такого вида
const obj1 = {1: 'Что-то', 3: 'что-то еще', 89: '...', type: 'test'};

// Проверяем, если у нас объект вложенный, даем тип и возвращаем объект такого вида
const obj2 = {
  0: {
    1: {},
    2: {},
    3: {}
  },
  type: 'test2'
};

То есть, нужно проверить к нам пришел вложенный объект или обычный


Ответы (1 шт):

Автор решения: SwaD

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

Однако, типом object обладают массивы и null, их надо исключить из условия.

Преобразуем объект в массив значений методом Object.values(obj) и в цикле будем проверять значение на тип данных. Как только встретим объект, цикл прерываем.

Создадим фукнцию, в которой реализуем необходимые проверки и мутирование переданного объекта, добавлением ключа test

function testObject(obj) {
  let test = 'test'; // Если вложенных объектов нет
  for (let item of Object.values(obj)) {
    if (item !== null && typeof item === 'object' && !Array.isArray(item) ) {
      // Нашли объект
      test = 'test2';
      break; // прерывем цикл
    }
  }
  obj['test'] = test; // Добавляем ключ объекту
}

В целом, можно и не преобразовывать объект в массив значений и обойти объект так:

function testObject(obj) {
  let test = 'test';
  for (let item in obj) {
    if (obj[item] !== null && typeof obj[item] === 'object' && !Array.isArray(obj[item])) {
      test = 'test2';
      break;
    }
  }
  obj['test'] = test;
}

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

function testObject(obj) {
  const newObj = { ...obj } // Делаем поверхностное копирование
  let test = 'test';
  for (let item of Object.values(obj)) {
    if (item !== null && typeof item === 'object' && !Array.isArray(item)) {
      test = 'test2';
      break;
    }
  }
  newObj['test'] = test;
  return newObj;
}

Ниже набор тестов для разных объектов:

const obj1 = {
  1: 'Что-то',
  3: 'что-то еще',
  89: '...'
};

// Проверяем, если у нас объект вложенный, даем тип и возвращаем объект такого вида
const obj2 = {
  0: {
    1: {},
    2: {},
    3: {}
  }
};

const obj3 = {
  0: 0,
  1: [1, 2]
}

const obj4 = {
  0: 1,
  1: null
}

const obj5 = {
  0: 2,
  2: undefined
}

function testObject(obj) {
  let test = 'test';
  for (let item of Object.values(obj)) {
    if (item !== null && typeof item === 'object' && !Array.isArray(item)) {
      test = 'test2';
      break;
    }
  }
  obj['test'] = test;
}

testObject(obj1);
console.log('obj1', obj1);

testObject(obj2);
console.log('obj2', obj2)

testObject(obj3);
console.log('obj3', obj3)

testObject(obj4);
console.log('obj4', obj4)

testObject(obj5);
console.log('obj5', obj5)

→ Ссылка