代码之家  ›  专栏  ›  技术社区  ›  yolenoyer

仅复制对象的一部分的优雅方法[复制]

  •  5
  • yolenoyer  · 技术社区  · 7 年前

    这个问题已经有了答案:

    我想从一个更大的对象中创建一个新的对象,只复制其中的一些属性。我所知道的所有解决方案都不是很优雅,我想知道是否有更好的选择,如果可能的话,是本地的(没有像下面代码末尾那样的附加功能)?

    下面是我现在通常做的事情:

    // I want to keep only x, y, and z properties:
    let source = {
        x: 120,
        y: 200,
        z: 150,
        radius: 10,
        color: 'red',
    };
    
    // 1st method (not elegant, especially with even more properties):
    let coords1 = {
        x: source.x,
        y: source.y,
        z: source.z,
    };
    
    // 2nd method (problem: it pollutes the current scope):
    let {x, y, z} = source, coords2 = {x, y, z};
    
    // 3rd method (quite hard to read for such simple task):
    let coords3 = {};
    for (let attr of ['x','y','z']) coords3[attr] = source[attr];
    
    // Similar to the 3rd method, using a function:
    function extract(src, ...props) {
        let obj = {};
        props.map(prop => obj[prop] = src[prop]);
        return obj;
    }
    let coords4 = extract(source, 'x', 'y', 'z');
    
    7 回复  |  直到 7 年前
        1
  •  12
  •   Marco    7 年前

    一种方法是通过对象销毁和箭头函数:

    let source = {
        x: 120,
        y: 200,
        z: 150,
        radius: 10,
        color: 'red',
    };
    
    let result = (({ x, y, z }) => ({ x, y, z }))(source);
    
    console.log(result);

    它的工作方式是箭头函数 (({ x, y, z }) => ({ x, y, z })) 立即呼叫 source 作为参数。它会破坏 来源 进入之内 x , y z ,然后立即将其作为新对象返回。

        2
  •  5
  •   Nina Scholz    7 年前

    只需要一个函数。

    const extract = ({ x, y, z }) => ({ x, y, z });
    
    let source = { x: 120, y: 200, z: 150, radius: 10, color: 'red' };
    
    console.log(extract(source));

    另一种解决方案是对具有目标属性的目标对象进行破坏。

    let source = { x: 120, y: 200, z: 150, radius: 10, color: 'red' }, 
        target = {};
    
    ({ x: target.x, y: target.y, z: target.z } = source);
    
    console.log(target);
        3
  •  3
  •   Jonas Wilms    7 年前

    可能是被摧毁的生活?:

    const coords = (({x, y, z}) => ({x, y, z}))(source);
    
        4
  •  1
  •   Emissary    7 年前

    对于类似这样的简单情况,其他答案中提到的对象破坏非常简单,但是在处理较大的结构时,当您对属性名进行双重处理时,看起来有点麻烦。

    扩展你自己的答案-如果你要写一个 extract 实用工具(我会自己滚来玩的)您可以通过转换它使其更加灵活——允许您交换参数的顺序(尤其是将数据源放在最后),同时在接受属性名时仍然是可变的。

    我会考虑这个签名: extract = (...props) => src => { ... } 更优雅,因为它允许在编写新的命名函数时进行更大程度的重用:

    const extract = (...props) => src => 
        Object.entries(src).reduce(
            (obj, [key, val]) => (
                props.includes(key) && (obj[key] = val), 
                obj
        ), {})
    
    const getCoords = extract('x', 'y', 'z')
    
    const source = {
        x: 120,
        y: 200,
        z: 150,
        radius: 10,
        color: 'red'
    }
    
    console.log(getCoords(source))
        5
  •  1
  •   Vikasdeep Singh    7 年前

    你可以像下面那样通过 Spread Operator

    let source = {
        x: 120,
        y: 200,
        z: 150,
        radius: 10,
        color: 'red',
    };
    
    let {radius, color, ...newObj} = source;
    console.log(newObj);
        6
  •  0
  •   Leonid Pyrlia    7 年前

    你可以试试 reduce 结束 [x,y,z] 数组:

    let source = {
        x: 120,
        y: 200,
        z: 150,
        radius: 10,
        color: 'red',
    };
    
    const coords = ['x','y','z'].reduce((a,c) => Object.assign(a,{[c]: source[c]}), {});
    
    console.log(coords);
    
        7
  •  0
  •   Napas    7 年前

    第一种方法优雅易读。

    请不要用一些解决方法来混淆简单的操作。其他需要维护此代码的人,包括将来的自己,将来都会非常感激。

    推荐文章