Скажем, у меня есть объект:
elmo = {
color: 'red',
annoying: true,
height: 'unknown',
meta: { one: '1', two: '2'}
};
Я хочу сделать новый объект с подмножеством его свойств.
// pseudo code
subset = elmo.slice('color', 'height')
//=> { color: 'red', height: 'unknown' }
Как я могу достичь этого?
javascript
Кристиан Шленскер
источник
источник
emo.slice
на первый взгляд.Ответы:
Использование уничтожения объектов и сокращения свойств
От Филиппа Кьюиша:
источник
let unwrap = ({a, c}) => ({a, c}); let unwrap2 = function({a, c}) { return { a, c }; }; let picked = unwrap({ a: 5, b: 6, c: 7 });
const { b, ...picked } = object
, создатьpicked
как{ a: 5, c: 7 }
. Вы указали просто удалить б. Ваш эслинт, вероятно, будет раздражен тем, что вы объявили переменную, которую вы не используете.Я предлагаю взглянуть на Лодаш ; в нем много полезных функций.
Например
pick()
будет именно то, что вы ищете:играть на скрипке
источник
_.omit(elmo, ['voice'])
чтобы вернуть все, ноvoice
Если вы используете ES6, есть очень лаконичный способ сделать это, используя деструктуризацию. Деструктурирование позволяет легко добавлять объекты к объекту с использованием разворота, но также позволяет создавать подмножества объектов таким же образом.
источник
Хотя это немного более многословно, вы можете выполнить то, что другие рекомендовали подчеркивание / lodash 2 года назад, используя Array.prototype.reduce .
Этот подход решает его с другой стороны: вместо того, чтобы взять объект и передать ему имя свойства для извлечения, взять массив имен свойства и преобразовать их в новый объект.
Хотя в простейшем случае это более многословно, обратный вызов здесь довольно удобен, так как вы можете легко удовлетворить некоторые общие требования, например, изменить свойство «color» на «color» для нового объекта, сгладить массивы и т. Д. - любой из то, что вам нужно сделать при получении объекта из одной службы / библиотеки и создании нового объекта, необходимого где-то еще. Хотя подчеркивание / lodash - отличные, хорошо реализованные библиотеки, я предпочитаю подход, основанный на меньшей зависимости от поставщика, и более простой и последовательный подход, когда моя логика построения подмножеств становится более сложной.
редактировать: ES7 версия того же:
редактировать: хороший пример для карри тоже! Имейте функцию 'pick', возвращающую другую функцию.
Вышеприведенный пример довольно близок к другому методу, за исключением того, что он позволяет создавать «сборщик» на лету. например
Что особенно приятно в этом подходе, так это то, что вы можете легко передавать выбранные «пики» во все, что принимает функцию, например
Array#map
:источник
function showToy({ color, height }) {
, поместил бы в область действия только то, что вам нужно.reduce
Подход главным образом имеет смысл , когда вы упрощая объекты для сериализации.const pick = (obj, props) => props.reduce((a, e) => (a[e] = obj[e], a), {});
fetch
), поэтому я бы рекомендовал добавить комментарий, объясняющий использование оператора запятой.ES6 деструктуризация
Разрушающий синтаксис позволяет деструктурировать и рекомбинировать объект либо с параметрами функции, либо с переменными.
Ограничение состоит в том, что список ключей предопределен, их нельзя перечислять в виде строк, как упоминается в вопросе. Разрушение становится более сложным, если ключ не алфавитно-цифровой, например
foo_bar
.Недостатком является то, что для этого требуется продублировать список ключей, это приводит к подробному коду в случае, если список длинный. Поскольку в этом случае деструктурирование дублирует синтаксис литерала объекта, список можно скопировать и вставить как есть.
Плюс в том, что это эффективное решение, естественное для ES6.
IIFE
Временные переменные
Список строк
Произвольный список выбранных ключей состоит из строк, как того требует вопрос. Это позволяет не предопределять их и использовать переменные, которые содержат имена ключей, например
pick(obj, 'foo', someKey, ...moreKeys)
.Однострочник становится короче с каждым выпуском JS.
ES5
ES6
Или с запятой оператор:
ES2019
ECMAScript 2017 имеет
Object.entries
иArray.prototype.includes
, ECMAScript 2019 имеетObject.fromEntries
, они могут быть заполнены при необходимости и сделать задачу проще:Однострочник
pick
может быть переписан как вспомогательная функция, аналогичная Lodash, илиomit
где список ключей передается через аргументы:Примечание о пропавших ключах
Основное различие между деструктуризацией и обычной Lodash-подобной
pick
функцией заключается в том, что деструктуризация включает в себя несуществующие выбранные ключи соundefined
значением в подмножестве:Такое поведение может быть или не быть желательным. Его нельзя изменить для деструктурирования синтаксиса.
Хотя
pick
можно изменить, чтобы включить отсутствующие ключи, выполнив итерацию списка выбранных ключей:источник
obj
переменная является переменной, которая хранит объект. Если имя вашей переменной отличается, используйте его вместоobj
.Object.keys(obj)
. Сонный.Нет ничего подобного встроенной в базовую библиотеку, но вы можете использовать деструктуризацию объектов, чтобы сделать это ...
Вы также можете написать служебную функцию сделать это ...
Библиотеки, такие как Lodash, также есть
_.pick()
.источник
Я добавляю этот ответ, потому что ни один из ответов не используется
Comma operator
.Это очень легко с
destructuring assignment
и,
операторомС некоторым улучшением для динамического присваивания свойств это может выглядеть так:
источник
'use strict'
). Я получаюReferenceError: a is not defined
.a
иc
- будьте осторожны, чтобы случайно не перезаписать локальные или глобальные переменные в зависимости от контекста. (Принятый ответ позволяет избежать этой проблемы, используя две локальные переменные во встроенной функции, которая выходит из области видимости после немедленного выполнения.)Еще одно решение:
Это выглядит намного более читабельным для меня, чем практически любой ответ, но, возможно, это только я!
источник
subset = {color: elmo.color, height: elmo.color}
, у меня был бы по крайней мере ... ну, возможно, ни копейки.Вы также можете использовать Lodash .
В дополнение, скажем, у вас есть массив "elmo":
Если вы хотите того же поведения, используя lodash, вы просто:
источник
Разбиение на динамически именованные переменные невозможно в JavaScript, как обсуждалось в этом вопросе .
Чтобы динамически устанавливать ключи , вы можете использовать функцию Reduce без изменения объекта следующим образом:
ниже приведена версия, использующая метод уменьшения с одним клоном (обновление исходного значения, переданного для уменьшения).
источник
Решение TypeScript:
Информация о наборе даже допускает автозаполнение:
Кредит на DefinitiveTyped за
U extends keyof T
трюк!источник
Используйте
pick
метод библиотеки lodash, если вы уже используете.https://lodash.com/docs/4.17.10#pick
источник
Динамическое решение
Показать фрагмент кода
источник
Просто по-другому ...
Вы можете использовать эту функцию с массивом объектов =)
источник
Как насчет:
источник
false
(или ложно). jsfiddle.net/nfAs8keys[i] in obj
.Это работает для меня в консоли Chrome. Есть проблемы с этим?
источник
Разрушающее присваивание с динамическими свойствами
Это решение применимо не только к вашему конкретному примеру, но и в более широком смысле:
Вы можете легко определить
subset4
и т.д., чтобы принять во внимание больше свойств.источник
Хороший старый
Array.prototype.reduce
:этот ответ использует магический запятую, также: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comma_Operator
если вы хотите стать действительно модным, это более компактно:
Собираем все вместе в многократно используемую функцию:
источник
преобразовать аргументы в массив
использовать,
Array.forEach()
чтобы выбрать недвижимостьисточник
источник
Пытаться
источник
Добавляя мои 2 цента к ответу Ивана Носова :
В моем случае мне нужно было «вырезать» много ключей из объекта, чтобы это стало уродливым, очень быстрым и не очень динамичным решением:
Итак, вот динамическое решение с использованием eval:
источник
Вы можете расширить jquery, если хотите, вот пример кода для одного фрагмента:
Вот скрипка для того же: http://jsfiddle.net/w633z/
источник