How one can write a function, which takes only few attributes in most-compact way in ES6?
如何编写一个在ES6中以最紧凑的方式只接受很少属性的函数?
I've came up with solution using destructuring + simplified object literal, but I don't like that list of fields is repeated in the code.
我已经提出了使用析构+简化对象文字的解决方案,但是我不喜欢在代码中重复列出字段。
Is there an even slimmer solution?
有更苗条的解决方案吗?
(v) => {
let { id, title } = v;
return { id, title };
}
7 个解决方案
#1
89
Here's something slimmer, although it doesn't avoid repeating the list of fields. It uses "parameter destructuring" to avoid the need for the v
parameter.
这里有一些更小的东西,尽管它不会避免重复字段列表。它使用“参数破坏”来避免对v参数的需要。
({id, title}) => ({id, title})
@EthanBrown's solution is more general. Here is a more idiomatic version of it which uses Object.assign
, and computed properties (the [p]
part):
@乙烷的解更一般。这里有一个使用Object的更习惯的版本。分配和计算属性([p]部分):
function pick(o, ...props) {
return Object.assign({}, ...props.map(prop => ({[prop]: o[prop]})));
}
If we want to preserve the properties' attributes, such as configurable
and getters and setters, while also omitting non-enumerable properties, then:
如果我们想要保留属性的属性,比如可配置的和getter和setter,同时还忽略不可枚举的属性,那么:
function pick(o, ...props) {
var has = p => o.propertyIsEnumerable(p),
get = p => Object.getOwnPropertyDescriptor(o, p);
return Object.defineProperties({},
Object.assign({}, ...props
.filter(prop => has(prop))
.map(prop => ({prop: get(props)})))
);
}
#2
34
I don't think there's any way to make it much more compact than your answer (or torazburo's), but essentially what you're trying to do is emulate Underscore's pick
operation. It would be easy enough to re-implement that in ES6:
我不认为有什么方法能比你的答案(或toraz共夫公司)更紧凑,但本质上你要做的是模仿下划线的挑选操作。在ES6中重新实现这一点非常容易:
function pick(o, ...fields) {
return fields.reduce((a, x) => {
if(o.hasOwnProperty(x)) a[x] = o[x];
return a;
}, {});
}
Then you have a handy re-usable function:
然后你就有了一个方便的可重复使用的功能:
var stuff = { name: 'Thing', color: 'blue', age: 17 };
var picked = pick(stuff, 'name', 'age');
#3
13
The trick to solving this as a one-liner is to flip the approach taken: Instead of starting from original object orig
, one can start from the keys they want to extract.
解决这一问题的窍门是:从原始的对象orig开始,可以从他们想要提取的键开始。
Using Array#reduce
one can then store each needed key on the empty object which is passed in as the initialValue
for said function.
使用数组#reduce,可以将每个需要的键存储在空对象上,该对象作为该函数的initialValue传入。
Like so:
像这样:
const orig = {
id: 123456789,
name: 'test',
description: '…',
url: 'https://…',
};
const filtered = ['id', 'name'].reduce((result, key) => { result[key] = orig[key]; return result; }, {});
console.log(filtered); // Object {id: 123456789, name: "test"}
#4
5
TC39's object rest/spread properties proposal will make this pretty slick:
TC39的对象rest/spread properties提议将使这一切变得非常巧妙:
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
z; // { a: 3, b: 4 }
(It does have the downside of creating the x
and y
variables which you may not need.)
(它确实有创建x和y变量的缺点,而您可能不需要这些变量。)
#5
2
A tiny bit shorter solution using the comma operator:
使用逗号运算符的更短的解:
const pick = (O, ...K) => K.reduce((o, k) => (o[k]=O[k], o), {})
#6
0
I have similar to Ethan Brown's solution, but even shorter - pick
function. Another function pick2
is a bit longer (and slower), but allows to rename properties in the similar to ES6 manner.
我有类似伊桑布朗的解决方案,但更短的选择函数。另一个函数pick2稍微长一点(更慢),但是允许以类似于ES6的方式重命名属性。
const pick = (o, ...props) => props.reduce((r, p) => p in o ? {...r, [p]: o[p]} : r, {})
const pick2 = (o, ...props) => props.reduce((r, expr) => {
const [p, np] = expr.split(":").map( e => e.trim() )
return p in o ? {...r, [np || p]: o[p]} : r
}, {})
Here is the usage example:
下面是使用示例:
const d = { a: "1", c: "2" }
console.log(pick(d, "a", "b", "c")) // -> { a: "1", c: "2" }
console.log(pick2(d, "a: x", "b: y", "c")) // -> { x: "1", c: "2" }
#7
0
I required this sollution but I didn't knew if the proposed keys were available. So, I took @torazaburo answer and improved for my use case:
我需要这个解决方案,但我不知道提议的钥匙是否可用。因此,我采用@torazaburo的答案并对我的用例进行了改进:
function pick(o, ...props) {
return Object.assign({}, ...props.map(prop => {
if (o[prop]) return {[prop]: o[prop]};
}));
}
// Example:
var person = { name: 'John', age: 29 };
var myObj = pick(person, 'name', 'sex'); // { name: 'John' }
#1
89
Here's something slimmer, although it doesn't avoid repeating the list of fields. It uses "parameter destructuring" to avoid the need for the v
parameter.
这里有一些更小的东西,尽管它不会避免重复字段列表。它使用“参数破坏”来避免对v参数的需要。
({id, title}) => ({id, title})
@EthanBrown's solution is more general. Here is a more idiomatic version of it which uses Object.assign
, and computed properties (the [p]
part):
@乙烷的解更一般。这里有一个使用Object的更习惯的版本。分配和计算属性([p]部分):
function pick(o, ...props) {
return Object.assign({}, ...props.map(prop => ({[prop]: o[prop]})));
}
If we want to preserve the properties' attributes, such as configurable
and getters and setters, while also omitting non-enumerable properties, then:
如果我们想要保留属性的属性,比如可配置的和getter和setter,同时还忽略不可枚举的属性,那么:
function pick(o, ...props) {
var has = p => o.propertyIsEnumerable(p),
get = p => Object.getOwnPropertyDescriptor(o, p);
return Object.defineProperties({},
Object.assign({}, ...props
.filter(prop => has(prop))
.map(prop => ({prop: get(props)})))
);
}
#2
34
I don't think there's any way to make it much more compact than your answer (or torazburo's), but essentially what you're trying to do is emulate Underscore's pick
operation. It would be easy enough to re-implement that in ES6:
我不认为有什么方法能比你的答案(或toraz共夫公司)更紧凑,但本质上你要做的是模仿下划线的挑选操作。在ES6中重新实现这一点非常容易:
function pick(o, ...fields) {
return fields.reduce((a, x) => {
if(o.hasOwnProperty(x)) a[x] = o[x];
return a;
}, {});
}
Then you have a handy re-usable function:
然后你就有了一个方便的可重复使用的功能:
var stuff = { name: 'Thing', color: 'blue', age: 17 };
var picked = pick(stuff, 'name', 'age');
#3
13
The trick to solving this as a one-liner is to flip the approach taken: Instead of starting from original object orig
, one can start from the keys they want to extract.
解决这一问题的窍门是:从原始的对象orig开始,可以从他们想要提取的键开始。
Using Array#reduce
one can then store each needed key on the empty object which is passed in as the initialValue
for said function.
使用数组#reduce,可以将每个需要的键存储在空对象上,该对象作为该函数的initialValue传入。
Like so:
像这样:
const orig = {
id: 123456789,
name: 'test',
description: '…',
url: 'https://…',
};
const filtered = ['id', 'name'].reduce((result, key) => { result[key] = orig[key]; return result; }, {});
console.log(filtered); // Object {id: 123456789, name: "test"}
#4
5
TC39's object rest/spread properties proposal will make this pretty slick:
TC39的对象rest/spread properties提议将使这一切变得非常巧妙:
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
z; // { a: 3, b: 4 }
(It does have the downside of creating the x
and y
variables which you may not need.)
(它确实有创建x和y变量的缺点,而您可能不需要这些变量。)
#5
2
A tiny bit shorter solution using the comma operator:
使用逗号运算符的更短的解:
const pick = (O, ...K) => K.reduce((o, k) => (o[k]=O[k], o), {})
#6
0
I have similar to Ethan Brown's solution, but even shorter - pick
function. Another function pick2
is a bit longer (and slower), but allows to rename properties in the similar to ES6 manner.
我有类似伊桑布朗的解决方案,但更短的选择函数。另一个函数pick2稍微长一点(更慢),但是允许以类似于ES6的方式重命名属性。
const pick = (o, ...props) => props.reduce((r, p) => p in o ? {...r, [p]: o[p]} : r, {})
const pick2 = (o, ...props) => props.reduce((r, expr) => {
const [p, np] = expr.split(":").map( e => e.trim() )
return p in o ? {...r, [np || p]: o[p]} : r
}, {})
Here is the usage example:
下面是使用示例:
const d = { a: "1", c: "2" }
console.log(pick(d, "a", "b", "c")) // -> { a: "1", c: "2" }
console.log(pick2(d, "a: x", "b: y", "c")) // -> { x: "1", c: "2" }
#7
0
I required this sollution but I didn't knew if the proposed keys were available. So, I took @torazaburo answer and improved for my use case:
我需要这个解决方案,但我不知道提议的钥匙是否可用。因此,我采用@torazaburo的答案并对我的用例进行了改进:
function pick(o, ...props) {
return Object.assign({}, ...props.map(prop => {
if (o[prop]) return {[prop]: o[prop]};
}));
}
// Example:
var person = { name: 'John', age: 29 };
var myObj = pick(person, 'name', 'sex'); // { name: 'John' }