Каков самый быстрый способ в ES7 выполнить слияние объекта объекта строки?

У меня есть объект, содержащий объект, содержащий строку.

  const userKeyframes = {
    from: {
      opacity: 1,
    },
    '40%': {
      transform: 'skew(20deg)',
      opacity: 1,
    },
    '80%': {
      transform: 'skew(-5deg)',
      opacity: 1,
    },
    to: {
      transform: 'translate3d(-100%, 0, 0) skew(10deg)',
      opacity: 0,
    },
  };

Я обычно так поступаю с ImmutableJS:

  const merge = fromJS(make(options)).mergeDeep(userKeyframes);

Я пробовал это (https://www.webpackbin.com/bins/-KiVy6f5eWDb44W4dXtE ), но не сработало:

  const merge = make(options);
  Object.keys(userKeyframes).forEach((key) => {
    Object.assign(merge[key], userKeyframes[key]);
  });

Я не думаю, что не хочу оставлять immutableJS только для этого.

Каков самый быстрый способ в ES7 выполнить слияние двух из них без какой-либо сторонней библиотеки?


person Dimitri Kopriwa    schedule 24.04.2017    source источник
comment
Больше похоже на оператор возврата, чем на объект.   -  person Omri Luzon    schedule 24.04.2017
comment
Что вы имеете в виду под самым эффективным? Обратите внимание, что стрелочные функции не обязательно более эффективны, чем function(){}, см. Оптимизированы ли функции, обозначенные жирной стрелкой, аналогично именованным функциям?   -  person guest271314    schedule 24.04.2017
comment
Под самым быстрым я подразумеваю, что алгоритм не должен иметь возможность выполнять deepMerge   -  person Dimitri Kopriwa    schedule 24.04.2017
comment
@BigDong Похоже, вы уже нашли решение с помощью своего цикла и Object.assign   -  person Bergi    schedule 24.04.2017
comment
Я не пытаюсь это написать webpackbin.com/bins/-KiVy6f5eWDb44W4dXtE   -  person Dimitri Kopriwa    schedule 24.04.2017
comment
но не сработало Можете ли вы описать, что не сработало, и создать набор сниппетов для демонстрации?   -  person guest271314    schedule 24.04.2017


Ответы (1)


Проблема в том, что вы предполагаете, что merge[key] существует для всех ключей, но, очевидно, это не гарантируется. Таким образом, Object.assign(merge[key], .......) может иметь первый аргумент как undefined, что не дает желаемого эффекта (но приводит к ошибке).

Вместо этого создайте новый объект для первого аргумента и присвойте результат merge[key]:

Object.keys(userKeyframes).forEach((key) => {
    merge[key] = Object.assign({}, userKeyframes[key]);
});

Однако приведенное выше будет перезаписывать все, что находится в merge[key], до того, как произойдет назначение. Есть две альтернативы, которые вы можете использовать по-другому:

Вы можете выполнить назначение только тогда, когда merge[key] еще не существует, поэтому вы можете назначить userKeyframes[key] только в этом случае:

Object.keys(userKeyframes).forEach((key) => {
    if (!(key in merge)) {
        merge[key] = Object.assign({}, userKeyframes[key]);
    }
});

Или, в качестве альтернативы, вы можете действительно объединить два объекта, когда оба уже существуют, то есть вы хотите иметь все свойства из userKeyframes[key], но также сохранить любые другие свойства, которые уже были в merge[key], которые будут уничтожены первым решением.

В этом случае предоставьте merge[key] и userKeyframes[key] в качестве 2 nd и 3 rd аргументов для Object.assign, учитывая, что значения undefined во всех, кроме первого аргумента, не представляют проблемы:

Object.keys(userKeyframes).forEach((key) => {
    merge[key] = Object.assign({}, merge[key], userKeyframes[key]);
});

В этом последнем фрагменте кода, когда merge[key] уже имеет значение, его свойства, которые не встречаются в userKeyframes[key], останутся, а те, которые имеют, будут перезаписаны свойствами из userKeyframes[key], как указано в документация по MDN:

Свойства более поздних источников будут ... перезаписывать более ранние.

person trincot    schedule 24.04.2017
comment
Мне нравится последний вариант, но если ключ присутствует в обоих, то способ, которым вы его написали, заставит значение приложения переопределить значение пользователя, чего я не хочу. - person Dimitri Kopriwa; 24.04.2017
comment
Последний вариант не отменяет то, что уже есть в объекте merge. Он просто переназначит то, что уже было там, из-за последнего аргумента Object.assign: последний аргумент переопределит любой из предыдущих аргументов. По общему признанию, если для одного и того же ключа объект ключевых кадров имел больше свойств в объекте, назначенном тому же ключу, они будут скопированы рядом с существующими свойствами merge. - person trincot; 24.04.2017
comment
Таким образом, переход на merge[key] = Object.assign({}, merge[key], userKeyframes[key]); даст ожидаемый результат. - person Dimitri Kopriwa; 25.04.2017
comment
Если запись в объекте userKeyframes должна иметь приоритет, то действительно поместите ее последней. - person trincot; 25.04.2017