Руйнування ES6
Синтаксис деструктуризації дозволяє деструктурувати та рекомбінувати об'єкт із параметрами функції чи змінними.
Обмеження полягає в тому, що список ключів визначений заздалегідь, вони не можуть бути вказані як рядки, як зазначається в питанні. Деструкція стає складнішою, якщо ключ не буквено-цифровий, наприклад foo_bar.
Мінусом є те, що для цього потрібно дублювати список ключів, це призводить до багатослівного коду, якщо список довгий. Оскільки деструктуризація дублює синтаксис буквеного об'єкта в цьому випадку, список можна скопіювати та вставити як є.
Перевага полягає в тому, що це ефективне рішення, яке є природним для ES6.
IIFE
let subset = (({ foo, bar }) => ({ foo, bar }))(obj); // dupe ({ foo, bar })
Тимчасові змінні
let { foo, bar } = obj;
let subset = { foo, bar }; // dupe { foo, bar }
Список рядків
Довільний список вибраних клавіш складається з рядків, як цього вимагає питання. Це дозволяє не визначати їх заздалегідь і використовувати змінні, що містять ключові імена, наприклад pick(obj, 'foo', someKey, ...moreKeys).
Одне вкладиш стає коротшим із кожним виданням JS.
ES5
var subset = Object.keys(obj)
.filter(function (key) {
return ['foo', 'bar'].indexOf(key) >= 0;
})
.reduce(function (obj2, key) {
obj2[key] = obj[key];
return obj2;
}, {});
ES6
let subset = Object.keys(obj)
.filter(key => ['foo', 'bar'].indexOf(key) >= 0)
.reduce((obj2, key) => Object.assign(obj2, { [key]: obj[key] }), {});
Або з комою:
let subset = Object.keys(obj)
.filter(key => ['foo', 'bar'].indexOf(key) >= 0)
.reduce((obj2, key) => (obj2[key] = obj[key], obj2), {});
ES2019
В ECMAScript 2017 є, Object.entriesа Array.prototype.includesECMAScript 2019 є Object.fromEntries, вони можуть бути заповнені за необхідності та полегшити завдання:
let subset = Object.fromEntries(
Object.entries(obj)
.filter(([key]) => ['foo', 'bar'].includes(key))
)
Однокласникpick може бути переписаний як допоміжна функція, подібна до Лодаша або omitтам, де список ключів передається через аргументи:
let pick = (obj, ...keys) => Object.fromEntries(
Object.entries(obj)
.filter(([key]) => keys.includes(key))
);
let subset = pick({ foo: 1, qux: 2 }, 'foo', 'bar'); // { foo: 1 }
Примітка про відсутні ключі
Основна відмінність руйнування від звичайної функції, подібної Лодашу, pickполягає в тому, що деструкція включає неіснуючі вибрані ключі зі undefinedзначенням у підмножині:
(({ foo, bar }) => ({ foo, bar }))({ foo: 1 }) // { foo: 1, bar: undefined }
Така поведінка може бути чи не бажаною. Його не можна змінити для деструктуризації синтаксису.
Хоча pickможна змінити, щоб включити відсутні ключі, повторивши список вибраних ключів:
let inclusivePick = (obj, ...keys) => Object.fromEntries(
keys.map(key => [key, obj[key]])
);
let subset = inclusivePick({ foo: 1, qux: 2 }, 'foo', 'bar'); // { foo: 1, bar: undefined }