在 JavaScript 中仅复制选定属性的最短方法是啥?

Posted

技术标签:

【中文标题】在 JavaScript 中仅复制选定属性的最短方法是啥?【英文标题】:What's the shortest way to copy only selected attributes in JavaScript?在 JavaScript 中仅复制选定属性的最短方法是什么? 【发布时间】:2021-07-12 21:28:33 【问题描述】:

给定以下两个对象:

let a =  foo: 'bar' ;

let b = 
  one: 1,
  two: 2,
  three: 3,
  four: 4,
  five: 5,
  six: 6,
  seven: 7
;

我们可以假设这些对象中的所有值都是原语。目标是将 一些 属性从对象 b 复制到对象 a,但不是全部。

示例:

a.one = b.one;
a.two = b.two;
// Do not copy item three
a.four = b.four;
a.five = b.five;
a.six = b.six;
// Do not copy item seven

在这个例子中,我们省略了属性 3 和 7,但我们也可以省略任何其他属性,甚至不仅仅是两个项目。如您所见,如果我们要处理许多属性,此解决方案可能会非常麻烦。

问题:在 2021 年使用现代 javascript 实现类似目标的最短 、最干净、最简单的解决方案是什么?

注意:对于解决方案,您可以假设给出了一个字符串数组。每个字符串代表一个应该被复制的值的键。因此,在上面的示例中,您可以假设给出了const keys = ['one', 'two', 'four', 'five', 'six'];

【问题讨论】:

您是否有一些数据结构可以告诉您应该或不应该复制哪些属性? @GabrielLupu 您可以假设有一个字符串数组。每个字符串代表一个应该被复制的值的键。因此,在上面的示例中,您可以假设给出了const keys = ['one', 'two', 'four', 'five', 'six']; 【参考方案1】:

我会在给定键的数组上使用forEach 来复制我需要的内容:

const a = 
  foo: 'bar'
;

const b = 
  one: 1,
  two: 2,
  three: 3,
  four: 4,
  five: 5,
  six: 6,
  seven: 7
;

const doCopy = ['two', 'five'];

doCopy.forEach(el => a[el] = b[el]);

console.log(a);

【讨论】:

我编辑了我的答案以使用单行。请检查一下。 @TimoErnst 我喜欢!干净简单。【参考方案2】:

最简单(最短)的可能仍然是一个循环:

const res = ;
for (const key of keys) res[key] = source[key];

你也可以用reduce写这个:

const res = keys.reduce((target, key) =>  target[key] = source[key]; return target , );
const res = keys.reduce((target, key) => Object.assign(target, [key]: source[key]), );

或者,相当优雅,使用Object.fromEntries

const res = Object.fromEntries(keys.map(key => [key, source[key]]));

(但这不支持分配给现有对象)。

【讨论】:

【参考方案3】:

这将是我的解决方案。即使它有效,我也不喜欢必须导入依赖项。想知道现代 JavaScript 是否有更好的内置解决方案。

util.js

export function copySelected(a, b, attrs) 
  for (let i=0; i < attrs.length; i+=1) 
    const attr = attrs[i];
    a[attr] = b[attr];
  
  return a;

用法:

import  copySelected  from './util';

let a =  foo: 'bar' ;

let b = 
  one: 1,
  two: 2,
  three: 3,
  four: 4,
  five: 5,
  six: 6,
  seven: 7
;

copySelected(a, b, ['one', 'two', 'four', 'five', 'six']);

【讨论】:

【参考方案4】:

见 cmets:

const keys = ['one', 'two', 'four', 'five', 'six'];

let a =  foo: 'bar' ;

let b = 
  one: 1,
  two: 2,
  three: 3,
  four: 4,
  five: 5,
  six: 6,
  seven: 7
;

// Loop over the array
keys.forEach(function(key)
  // If the b object contains the key specified in the array
  if(b[key])
    a[key] = b[key];  // copy that key to a
  
);

console.log(a);

【讨论】:

【参考方案5】:

您可以分配想要的属性。

a) 没有用于分配的数组

let a =  foo: 'bar' ,
    b =  one: 1, two: 2, three: 3, four: 4, five: 5, six: 6, seven: 7 ,
    keys = ['one', 'two', 'four', 'five', 'six'];

keys.forEach(k => Object.assign(a,  [k]: b[k] ));

console.log(a);

b) 带有一个用于赋值的数组

let a =  foo: 'bar' ,
    b =  one: 1, two: 2, three: 3, four: 4, five: 5, six: 6, seven: 7 ,
    keys = ['one', 'two', 'four', 'five', 'six'];

Object.assign(a, ...keys.map(k => ( [k]: b[k] )));

console.log(a);

【讨论】:

【参考方案6】:

您可以使用Object.assign 将过滤后的条目(使用keys 数组过滤键/值对)从b 添加到a

const a = 
  foo: 'bar'
;

const b = 
  one: 1,
  two: 2,
  three: 3,
  four: 4,
  five: 5,
  six: 6,
  seven: 7
;

const keys = ['one', 'two', 'four', 'five', 'six'];

const res = Object
  .assign(a, Object.fromEntries(Object.entries(b)
    .filter(([k, v]) => keys.includes(k))
  ))
  
console.log(res)

【讨论】:

【参考方案7】:

与@Timo 的答案相同,但带有映射函数和扩展运算符。

function copySelected(a, b, ...attrs) 
  attrs.map(x => a[x] = b[x]);
  return a;


let a =  foo: 'bar' ;

let b = 
  one: 1,
  two: 2,
  three: 3,
  four: 4,
  five: 5,
  six: 6,
  seven: 7
;

console.log( copySelected(a, b, 'one', 'two', 'four', 'five', 'six'));

【讨论】:

在作业中滥用 Array.prototype.map 会降低可读性,并无缘无故地增加开销。【参考方案8】:

以下是 ECMAScript 2021 的示例:

const b = 
  one: 1,
  two: 2,
  three: 3,
  four: 4,
  five: 5,
  six: 6,
  seven: 7
;

const copyFromThis = ['one','two']

const temp = Object.fromEntries(Object.entries(b).filter(([key , value])=>copyFromThis.includes(key) ))

console.log(temp)

您可以根据需要自定义它!

【讨论】:

以上是关于在 JavaScript 中仅复制选定属性的最短方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

使用 jQuery 创建帖子表单并提交它的最短方法是啥? [复制]

如何在swift 3的表格视图中仅更改选定行和未选定行的字体颜色和大小?

检查 JavaScript 中是不是存在深度嵌套对象属性的最简单方法是啥? [复制]

PHP 或 Javascript - 如何设置表单提交之间的最短时间

通过 URL 将用户所在的 URL 提交到另一个进程的最简洁、最短的 Javascript 是啥?

Backbone 中仅客户端的属性