Javascript простой объект переопределить по умолчанию

1

BSD

У меня есть простой объект, который я бы хотел переопределить с другим, в случае, если некоторые из свойств не существуют в объекте, его следует взять из заданного по умолчанию объекта, может быть глубоко вложенным

Ниже приведен пример объекта настроек по умолчанию

defaults = {
   name : 'Joe',
   options : {
      color : 'green',
      dates : {
         from : new Date,
         to   : new Date,
      }
   }
}

Вот предоставленный объект

settings = {
   name : 'David',
   options : {
      color : 'purple'
   }
}

Вот ожидаемый результат, комбинация между двумя...

final = {
   name : 'David',
   options : {
      color : 'purple',
      dates : {
         from : new Date,
         to   : new Date,
      }
   }
}

Есть ли простой способ достичь этого без использования каких-либо внешних библиотек? Я пробовал некоторые подходы (JSON.stringify/parse/iterating over objects/etc...), но не смог получить чистое решение... надеюсь, что oneliner

Любая помощь приветствуется...

Теги:
performance

4 ответа

2

Вот мой вклад.

Следует отметить, что код довольно длинный из-за характера shallow и deep копирования объекта.

Использование Object.assign(defaults, settings) объединит ваши объекты, но ваш ключ date будет удален, так как он выполняет мелкую копию объекта.

Ниже я использовал фрагмент, который я нашел о том, How to deep merge instead of shallow merge? пользователем с именем jhildenbiddle который выполняет deep слияние объекта и является immutable (не редактирует исходные массивы).


let defaults = {
  name: 'Joe',
  options: {
    color: 'green',
    dates: {
      from: new Date(),
      to: new Date(),
    }
  }
};

let settings = {
  name: 'David',
  options: {
    color: 'purple'
  }
};

function mergeDeep(...objects) {
  const isObject = obj => obj && typeof obj === 'object';

  return objects.reduce((prev, obj) => {
    Object.keys(obj).forEach(key => {
      const pVal = prev[key];
      const oVal = obj[key];

      if (Array.isArray(pVal) && Array.isArray(oVal)) {
        prev[key] = pVal.concat(...oVal);
      } else if (isObject(pVal) && isObject(oVal)) {
        prev[key] = mergeDeep(pVal, oVal);
      } else {
        prev[key] = oVal;
      }
    });

    return prev;
  }, {});
}

let final = mergeDeep(defaults, settings);

console.log(final);
2

Используйте этот параметр $.extend(true, {}, defaults,settings). Обратите внимание на порядок переменной json. В этом случае settings будут переопределять defaults если эти две переменные имеют одинаковый атрибут.

Если вы смотрите на чистый ответ JS. Вот код.

function extend(a, b){
    for (var key in b) {
        if (b.hasOwnProperty(key))
            a[key] = b[key];
            return a;
        }
    }
}
console.log(extend(defaults,settings));
  • 0
    jQuery не был включен в качестве тега, поэтому сообщите в своем посте, что вы используете jQuery :)
  • 0
    Понимаю. Но OP сказал, что OP попытался использовать JSON.stringify .
Показать ещё 1 комментарий
1

Это может привести к тому, что вручную будет установлено каждое значение, если изменения по умолчанию изменены.

final = {
      name : settings.name ? settings.name : "Joe",
      options {
        color: settings.color ? settings.color : "green",
        dates: {
          from : settings.dates.from ? settings.dates.from : new Date,
          to: settings.dates.to ? settings.dates.to : new Date
        }
      }
    }

Это, вероятно, будет работать лучше всего:

var final = Object.assign({}, default, settings);
  • 0
    Обновленный ответ, надеюсь, это поможет
0

Вы можете взглянуть на Object.assign

final = Object.assign(defaults, settings) 
  • 0
    Дата не назначается.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню