One-liner para tomar algunas propiedades del objeto en ES 6


¿Cómo se puede escribir una función, que toma solo unos pocos atributos de la manera más compacta en ES6?

Se me ocurrió una solución usando desestructuración + simplified object literal, pero no me gusta que la lista de campos se repita en el código.

¿ Hay una solución aún más delgada?

(v) => {
    let { id, title } = v;
    return { id, title };
}
Author: Michał Perłakowski, 2014-08-28

7 answers

Aquí hay algo más delgado, aunque no evita repetir la lista de campos. Utiliza "desestructuración de parámetros" para evitar la necesidad del parámetro v.

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

La solución de@EthanBrown es más general. Aquí hay una versión más idiomática de la misma que utiliza Object.assign, y propiedades calculadas (la parte [p]):

function pick(o, ...props) {
    return Object.assign({}, ...props.map(prop => ({[prop]: o[prop]})));
}

Si queremos preservar los atributos de las propiedades, tales como configurable y getters y setters, mientras también omitimos propiedades no enumerables, entonces:

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)})))
    );
}
 94
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-25 16:53:48

No creo que haya ninguna manera de hacerlo mucho más compacto que tu respuesta (o la de torazburo), pero esencialmente lo que estás tratando de hacer es emular la operación de Underscore pick . Sería bastante fácil volver a implementar que en ES6:

function pick(o, ...fields) {
    return fields.reduce((a, x) => {
        if(o.hasOwnProperty(x)) a[x] = o[x];
        return a;
    }, {});
}

Entonces tienes una práctica función reutilizable:

var stuff = { name: 'Thing', color: 'blue', age: 17 };
var picked = pick(stuff, 'name', 'age');
 36
Author: Ethan Brown,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-15 15:59:59

El truco para resolver esto como una línea única es cambiar el enfoque adoptado: En lugar de comenzar desde el objeto original orig, uno puede comenzar desde las claves que desea extraer.

Usando Array#reduce a continuación, se puede almacenar cada tecla necesaria en el objeto vacío que se pasa como initialValue para dicha función.

Así:

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"}
 16
Author: Bramus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-20 14:17:16

Una solución un poco más corta usando el operador de coma:

const pick = (O, ...K) => K.reduce((o, k) => (o[k]=O[k], o), {})
 6
Author: shesek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-15 19:12:21

La propuesta de TC39 object rest / spread properties hará que esto sea bastante ingenioso:

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

(Tiene la desventaja de crear las variables x y y que puede que no necesite.)

 5
Author: alxndr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-03 18:29:01

Tengo una función similar a la solución de Ethan Brown, pero aún más corta - pick. Otra función pick2 es un poco más larga (y más lenta), pero permite renombrar propiedades de manera similar a 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
}, {}) 

Aquí está el ejemplo de uso:

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" }
 1
Author: Alexandr Priezzhev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-04 16:45:23

Necesitaba esta sollución pero no sabía si las claves propuestas estaban disponibles. Por lo tanto, tomé @torazaburo respuesta y mejorado para mi caso de uso:

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' }
 0
Author: Alwin Kesler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-16 18:29:58