Phá hủy ES6
Cú pháp phá hủy cho phép cấu trúc lại và kết hợp lại một đối tượng, với các tham số hàm hoặc biến.
Hạn chế là một danh sách các khóa được xác định trước, chúng không thể được liệt kê dưới dạng chuỗi, như câu hỏi đề cập. Việc phá hủy trở nên phức tạp hơn nếu một khóa không phải là chữ và số, ví dụ foo_bar
.
Nhược điểm là điều này đòi hỏi phải sao chép danh sách các khóa, điều này dẫn đến mã dài dòng trong trường hợp danh sách dài. Vì việc hủy bỏ trùng lặp cú pháp đối tượng theo nghĩa đen trong trường hợp này, một danh sách có thể được sao chép và dán như vậy.
Ưu điểm là giải pháp hiệu quả của ES6 là tự nhiên.
IIFE
let subset = (({ foo, bar }) => ({ foo, bar }))(obj); // dupe ({ foo, bar })
Biến tạm thời
let { foo, bar } = obj;
let subset = { foo, bar }; // dupe { foo, bar }
Một danh sách các chuỗi
Danh sách các phím được chọn tùy ý bao gồm các chuỗi, như câu hỏi yêu cầu. Điều này cho phép không xác định trước chúng và sử dụng các biến có chứa tên chính, như pick(obj, 'foo', someKey, ...moreKeys)
.
Một lớp lót trở nên ngắn hơn với mỗi phiên bản 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] }), {});
Hoặc với toán tử dấu phẩy:
let subset = Object.keys(obj)
.filter(key => ['foo', 'bar'].indexOf(key) >= 0)
.reduce((obj2, key) => (obj2[key] = obj[key], obj2), {});
ES2019
ECMAScript 2017 có Object.entries
và Array.prototype.includes
, ECMAScript 2019 có Object.fromEntries
, chúng có thể được điền đầy đủ khi cần và giúp công việc dễ dàng hơn:
let subset = Object.fromEntries(
Object.entries(obj)
.filter(([key]) => ['foo', 'bar'].includes(key))
)
Một lớp lót có thể được viết lại dưới dạng hàm trợ giúp tương tự như Lodashpick
hoặc omit
nơi danh sách các khóa được truyền qua các đối số:
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 }
Một lưu ý về các phím bị thiếu
Sự khác biệt chính giữa pick
chức năng phá hủy và chức năng giống như thông thường là phá hủy bao gồm các khóa được chọn không tồn tại với undefined
giá trị trong một tập hợp con:
(({ foo, bar }) => ({ foo, bar }))({ foo: 1 }) // { foo: 1, bar: undefined }
Hành vi này có thể hoặc không được mong muốn. Nó không thể được thay đổi để phá hủy cú pháp.
Trong khi pick
có thể thay đổi để bao gồm các phím bị thiếu bằng cách lặp lại danh sách các phím được chọn thay thế:
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 }