如何编写一个函数,在 ES6 中以最紧凑的方式只需要很少的属性?
我想出了使用解构+简化对象文字的解决方案,但我不喜欢在代码中重复该字段列表。
有没有更苗条的解决方案?
(v) => {
let { id, title } = v;
return { id, title };
}
如何编写一个函数,在 ES6 中以最紧凑的方式只需要很少的属性?
我想出了使用解构+简化对象文字的解决方案,但我不喜欢在代码中重复该字段列表。
有没有更苗条的解决方案?
(v) => {
let { id, title } = v;
return { id, title };
}
这里有一些更苗条的东西,尽管它不会避免重复字段列表。它使用“参数解构”来避免对v
参数的需要。
({id, title}) => ({id, title})
(请参阅this other answer中的可运行示例)。
@EthanBrown 的解决方案更通用。这是它的一个更惯用的版本,它使用Object.assign
, 和计算属性([p]
部分):
function pick(o, ...props) {
return Object.assign({}, ...props.map(prop => ({[prop]: o[prop]})));
}
如果我们想保留属性的属性,例如configurable
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)})))
);
}
我认为没有任何方法可以使它比您的答案(或 torazburo 的)更紧凑,但基本上您要做的是模仿Underscore 的pick
操作。在 ES6 中重新实现它很容易:
function pick(o, ...fields) {
return fields.reduce((a, x) => {
if(o.hasOwnProperty(x)) a[x] = o[x];
return a;
}, {});
}
然后你有一个方便的可重用功能:
var stuff = { name: 'Thing', color: 'blue', age: 17 };
var picked = pick(stuff, 'name', 'age');
以单线方式解决此问题的诀窍是翻转所采用的方法:orig
可以从他们想要提取的键开始,而不是从原始对象开始。
然后使用Array#reduce
一个可以将每个需要的键存储在作为initialValue
所述函数传入的空对象上。
像这样:
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"}
或者...
const filtered = ['id', 'name'].reduce((result, key) => ({
...result,
[key]: orig[key]
}), {});
console.log(filtered); // Object {id: 123456789, name: "test"}
使用逗号运算符的一个更短的解决方案:
const pick = (O, ...K) => K.reduce((o, k) => (o[k]=O[k], o), {})
console.log(
pick({ name: 'John', age: 29, height: 198 }, 'name', 'age')
)
TC39 的 object rest/spread properties 提案将使这变得非常漂亮:
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
z; // { a: 3, b: 4 }
(它确实有创建你可能不需要的x
和变量的缺点。)y
ES6 是编写问题时的最新规范。正如这个答案中所解释的,在 ES2019 中的关键选择比在 ES6 中要短得多:
Object.fromEntries(
Object.entries(obj)
.filter(([key]) => ['foo', 'bar'].includes(key))
)
您可以使用对象解构从现有对象中解压缩属性并将它们分配给具有不同名称的变量- 一个新的、最初为空的对象的字段。
const person = {
fname: 'tom',
lname: 'jerry',
aage: 100,
}
let newPerson = {};
({fname: newPerson.fname, lname: newPerson.lname} = person);
console.log(newPerson);
目前有一个关于改进 JavaScript 对象速记语法的稻草人提案,它可以“挑选”命名属性而无需重复:
const source = {id: "68646", genre: "crime", title: "Scarface"};
const target = {};
Object.assign(target, {source.title, source.id});
console.log(picked);
// {id: "68646", title: "Scarface"}
不幸的是,该提案似乎不会很快实现。最后编辑于 2017 年 7 月,目前仍处于第 0 阶段的草稿,这表明作者可能已经放弃或忘记了它。
我能想到的最简洁的速记涉及一个不再使用的古老语言功能:
Object.assign(target, {...(o => {
with(o) return { id, title };
})(source)});
with
语句在严格模式下是被禁止的,这使得这种方法对于 99.999% 的现代 JavaScript 来说毫无用处。有点遗憾,因为这是我为该功能找到的唯一一个中规中矩的用途with
。
我有类似于 Ethan Brown 的解决方案,但更短 -pick
功能。另一个函数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
}, {})
这是使用示例:
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" }
我需要这个解决方案,但我不知道建议的密钥是否可用。所以,我接受了@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' }
受到https://stackoverflow.com/users/865693/shesek的 reduce 方法的启发:
const pick = (orig, keys) => keys.reduce((acc, key) => ({...acc, [key]: orig[key]}), {})
甚至使用逗号运算符(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comma_Operator)稍微短一些
const pick = (obj, keys) => keys.reduce((acc, key) => ((acc[key] = obj[key]), acc), {});
用法:
pick({ model : 'F40', manufacturer: 'Ferrari', productionYear: 1987 }, 'model', 'productionYear')
结果是:
{model: "F40", productionYear: 1987}