Деструктурировать массив в ключи свойств объекта

У меня есть массив значений, например:

const arr = [1,2,3];

Есть ли способ использовать деструктурирование для создания следующего вывода? Если нет, то как проще всего это сделать в ES6 (или новее)?

const obj = {
    one: 1,
    two: 2,
    three: 3
};

Я пробовал это, но думаю, это не работает, так как это синтаксис для вычисляемых ключей:

const arr = [1,2,3];
const obj = {
  [one, two, three] = arr
};

person CodingIntrigue    schedule 07.07.2016    source источник
comment
Исходной целью деструктурирования является извлечение значений из данных, хранящихся во (вложенных) объектах/массивах. В вашем примере вы создаете объект. В этом случае лучше подходит объектный литерал.   -  person    schedule 07.07.2016
comment
Использование вычисляемых свойств на самом деле вызовет обратную обычную проблему. Обычно, когда люди хотят использовать переменную в качестве ключа литерала объекта, это рассматривается как реквизит. Здесь вы хотите определить свойство, но оно будет рассматриваться как переменная (если этот синтаксис разрешен). Или, по крайней мере, это будет двусмысленно, если в скобках будет только один.   -  person    schedule 07.07.2016
comment
@squint Действительно, именно поэтому я надеялся на синтаксис, который использует деструктурирование а не вычисляемых свойств, но это не похоже на то, что это возможно. Я думаю, это имеет смысл, учитывая, что длинная форма на самом деле не намного длиннее, а просто повторяется.   -  person CodingIntrigue    schedule 07.07.2016
comment
Это выглядит убедительно синтаксис, за исключением двусмысленности { [foo]: ["bar"] }, которая должна быть обработана как неприятный частный случай.   -  person    schedule 07.07.2016


Ответы (6)


Я не верю, что есть какое-либо решение для структурирования/деструктурирования, позволяющее сделать это за один шаг, нет. Я хотел что-то подобное в этом вопросе. Старое := предложение соломенного человека, похоже, не работает новый список предложений, так что я не думаю, что сейчас вокруг этого много активности.

Этот ответ показывает очень аккуратную двухэтапную версию.

Но если это два шага, вы также можете использовать простой инициализатор объекта:

const arr = [1,2,3];
const obj = {
  one: arr[0],
  two: arr[1],
  three: arr[2]
};
console.log(obj);

Другой вариант — сделать это с несколькими временными массивами, но технически только с одним оператором (я не за это ратую, просто отмечаю это):

const arr = [1,2,3];
const obj = Object.fromEntries(
    ["one", "two", "three"].map((name, index) =>
        [name, arr[index]]
    )
);
console.log(obj);

person T.J. Crowder    schedule 07.07.2016
comment
Существует почти одношаговое решение без создания ненужных переменных. - person ; 07.07.2016
comment
@ LUH3417: почти одноэтапное = двухэтапное. :-) Но да, это еще один совершенно правильный подход. - person T.J. Crowder; 07.07.2016
comment
похоже, вы действительно можете деструктурировать свойства объекта, см. stackoverflow.com/a/49413688/4273291 или stackoverflow.com/a/57908036/4273291 ниже - person lohfu; 12.08.2020
comment
@lohfu - Да, вы можете (на самом деле я дал ссылку на решение, которое подходит в ответе). Вы можете деструктурировать во что-нибудь назначаемое. Но это еще два шага. - person T.J. Crowder; 12.08.2020

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

const arr = [1,2,3], o = {};    
({0:o.one, 1:o.two, 2:o.three} = arr);

Это работает без каких-либо дополнительных переменных и меньше повторяется. Тем не менее, это также требует двух шагов, если вы очень внимательны к этому.

Я не уверен, поможет ли это, поскольку вы упомянули вычисляемые свойства?!

person Community    schedule 07.07.2016
comment
Это страшно и удивительно одновременно. - person Qix - MONICA WAS MISTREATED; 09.08.2017
comment
В TypeScript я получаю здесь ошибку. Он говорит: Переменные области блока не могут быть повторно объявлены - person Marecky; 21.01.2021

С деструктурированием вы можете либо создавать новые переменные, либо назначать существующие переменные/свойства. Однако вы не можете объявить и переназначить в одном операторе.

const arr = [1, 2, 3],
    obj = {};

[obj.one, obj.two, obj.three] = arr;
console.log(obj);
// { one: 1, two: 2, three: 3 }

person adambullmer    schedule 21.03.2018

Используя деструктурирующее присваивание, можно присвоить объекту из массива

Пожалуйста, попробуйте этот пример:

const numbers = {};

[numbers.one, numbers.two, numbers.three] = [1, 2, 3]

console.log(numbers)

Спасибо мальчикам с http://javascript.info/, где я нашел похожий пример. Этот пример находится по адресу http://javascript.info/destructuring-assignment в разделе Назначить чему-либо в левосторонняя секция

person Mario    schedule 12.09.2019

Это отвечает немного другому требованию, но я пришел сюда в поисках ответа на эту потребность, и, возможно, это поможет другим в подобной ситуации.

Учитывая массив строк: a = ['one', 'two', 'three'] Какой хороший невложенный нециклический способ получения этого результирующего словаря: b = { one : 'one', two: ' два', три: 'три' } ?

const b = a.map(a=>({ [a]: a })).reduce((p, n)=>({ ...p, ...n }),{})

person corse32    schedule 30.08.2017
comment
Вы можете использовать Object.assign() с синтаксисом распространения вместо .reduce(): const o = Object.assign(...a.map(val => ({ [val]: val }))); - person gilly3; 25.09.2018

Вы можете легко добиться этого, используя _.zipObject от lodash.

const obj = _.zipObject(['one','two','three'], [1, 2, 3]);
console.log(obj); // { one: 1, two: 2, three: 3 }
person Technotronic    schedule 12.03.2020