Объединение нескольких объектов с уникальными ключами - PullRequest
1 голос
/ 21 июня 2020

Учитывая 2 или более объекта, мне нужно создать функцию, которая объединит все свойства с уникальными ключами в один объект без использования большинства функций более высокого порядка, таких как filter (), map (), reduce () и т.д. c.

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

_.defaults = function(obj) {
  var objectArray = Array.from(arguments);
  var resultObject = objectArray[0];
  for(var i=1; i<arguments.length; i++){
    if(Object.keys(resultObject)!==(Object.keys(objectArray[i]))){
      Object.assign(resultObject, objectArray[i]);
    }
  }
  return resultObject;
};
Я также пробовал это в строке 5, но безрезультатно
  

if(Object.keys(resultObject).includes(Object.keys(objectArray[i])) === false){

1 Ответ

0 голосов
/ 26 июля 2020

Половина вашей проблемы находится в этой строке:

    if(Object.keys(resultObject)!==(Object.keys(objectArray[i])))

Это условие всегда оценивается как true. Причина в том, что Object.keys возвращает массив. Массивы сравниваются по ссылке; это означает, что операторы ==, ===, !== и т.д. только проверяют, является ли левый массив тем же самым объектом, что и правый массив. Нет сравнения содержимого. Поскольку Object.keys каждый раз возвращает массив новый , два массива не могут сравниваться на равных.

Однако, даже если бы это было сравнение по содержимому, это не делай что хочешь. Например, рассмотрим эти два объекта:

// resultObject
{ a: 1, b: 2 }

// objectArray[i]
{ b: 3, c: 4 }

Условие будет оценивать ['a', 'b'] !== ['b', 'c'], что равно true независимо от того, сравниваете ли вы по ссылке или по содержимому.

Ваша вторая попытка та же проблема - всегда вычислять до true. Чтобы понять, почему, давайте заменим результаты Object.keys:

if(['a', 'b'].includes(['b', 'c']) === false)

Метод includes в основном задает следующий вопрос: «равен ли какой-либо из моих элементов аргументу?» Поскольку Object.keys всегда создает массив строк, вы спрашиваете, равна ли какая-либо из этих строк массиву, чего никогда не будет. Левая сторона === всегда false, поэтому условие в целом всегда будет true.

В результате вы всегда делаете это (другая половина вашей проблемы ):

      Object.assign(resultObject, objectArray[i]);

в приведенном выше примере это переопределяет клавишу b в resultObject, поскольку Object.assign не может знать, что вы хотите пропустить ключи, которые уже были установлены.

Интуитивно вам нужно проверить, есть ли какие-либо ключи в objectArray[i], которых еще нет в resultObject, а затем назначить только эти клавиши на resultObject. Это означает, что вы должны рассматривать ключи objectArray[i] один за другим.

Следующий код сделает это:

    var currentObject = objectArray[i];
    var keys = Object.keys(currentObject);
    for (var l = keys.length, j = 0; j < l; j++) {
      var key = keys[j];
      if (resultObject[key] === undefined) {
        resultObject[key] = currentObject[key];
      }
    }

Вы можете заменить им весь if - в исходном коде, и тогда он должен работать.

...