单行从ES 6中的对象获取一些属性

时间:2014-08-28 16:42:23

标签: javascript ecmascript-6 ecmascript-harmony destructuring ecmascript-next

如何编写一个函数,在ES6中以最紧凑的方式只占用少量属性?

我已经提出了使用解构+简化对象文字的解决方案,但我不喜欢在代码中重复字段列表。

是否有更纤薄的解决方案?

(v) => {
    let { id, title } = v;
    return { id, title };
}

11 个答案:

答案 0 :(得分:106)

虽然它不会重复字段列表,但这里有些更苗条。它使用"参数解构"避免需要v参数。

({id, title}) => ({id, title})

@ 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)})))
    );
}

答案 1 :(得分:41)

我认为没有办法让它比你的回答(或者torazburo)更紧凑,但基本上你要做的就是模仿{{ 3}}。在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');

答案 2 :(得分:18)

解决这个问题的方法是翻转所采用的方法:不是从原始对象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"}




答案 3 :(得分:10)

使用逗号运算符的简短解决方案:

const pick = (O, ...K) => K.reduce((o, k) => (o[k]=O[k], o), {})

答案 4 :(得分:7)

TC39's object rest/spread properties proposal会让这个很漂亮:

let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
z; // { a: 3, b: 4 }

(它确实存在创建您可能不需要的xy变量的缺点。)

答案 5 :(得分:1)

我与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" }

答案 6 :(得分:1)

一种方法可能是使用destructuring将属性分配给空对象。

let person = {
    fname:'tom',
    lname:'jerry',
    aage:100
}

let newPerson = {};

({fname: newPerson.fname, lname: newPerson.lname} = person);

console.log(newPerson);

答案 7 :(得分:1)

当前有一个strawman proposal用于改进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月,但仍为Stage 0的草稿,表明作者可能已放弃或遗忘了它。

ES5及更早版本(非严格模式)

我能想到的最简洁的速记涉及ancient language feature,没人再使用了:

Object.assign(target, {...(o => {
    with(o) return { id, title };
})(source)});
在严格模式下禁止使用

with语句,这使得99.999%的现代JavaScript都无法使用此方法。有点遗憾,因为这是我发现的with功能的唯一中途使用。 ?

答案 8 :(得分:0)

我需要这个解决方案,但我不知道提议的密钥是否可用。所以,我接受了@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' }

答案 9 :(得分:0)

ES6是撰写问题时的最新规范。如this answer中所述,ES2019中的密钥选择比ES6中的密钥选择显着缩短:

Object.fromEntries(
  Object.entries(obj)
  .filter(([key]) => ['foo', 'bar'].includes(key))
)

答案 10 :(得分:0)

https://stackoverflow.com/users/865693/shesek的归约方法启发:

const pick = (orig, ...keys) => keys.reduce((acc, key) => ({...acc, [key]: orig[key]}), {})

用法:

pick({ model : 'F40', manufacturer: 'Ferrari', productionYear: 1987 }, 'model', 'productionYear') 结果是: {model: "F40", productionYear: 1987}