在 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 - 如何设置表单提交之间的最短时间