除了一个键之外,如何克隆一个 JavaScript 对象?

IT技术 javascript ecmascript-6 ecmascript-harmony ecmascript-2016
2021-02-05 04:30:51

我有一个平面 JS 对象:

{a: 1, b: 2, c: 3, ..., z:26}

我想克隆除一个元素之外的对象:

{a: 1, c: 3, ..., z:26}

最简单的方法是什么(如果可能,最好使用 es6/7)?

6个回答

如果您使用Babel,您可以使用以下语法将属性 b 从 x 复制到变量 b 中,然后将其余属性复制到变量 y 中

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

并且将transpiled到:

"use strict";

function _objectWithoutProperties(obj, keys) {
  var target = {};
  for (var i in obj) {
    if (keys.indexOf(i) >= 0) continue;
    if (!Object.prototype.hasOwnProperty.call(obj, i)) continue;
    target[i] = obj[i];
  }
  return target;
}

var x = { a: 1, b: 2, c: 3, z: 26 };
var b = x.b;

var y = _objectWithoutProperties(x, ["b"]);
我做了一个let { b: _b, ...y } = x;跳过“未使用的变量”警告。
2021-03-15 04:30:51
@IlyaPalkin 有趣。虽然感觉有点懒惰,因为它并没有改变存在b范围内的事实
2021-03-21 04:30:51
如果您为未使用的变量整理代码,这将导致“未使用的变量 'b'”。警告。
2021-03-25 04:30:51
@RossAllenignoreRestSiblings在 v3.15.0(2017 年 2 月 3 日)中添加了一个选项请参阅:提交 c59a0ba
2021-04-06 04:30:51
如果您遇到 Module build failed: SyntaxError: Unexpected token,您可能需要添加 babel rest spread transform 插件。见 babeljs.io/docs/plugins/transform-object-rest-spread
2021-04-09 04:30:51
var clone = Object.assign({}, {a: 1, b: 2, c: 3});
delete clone.b;

或者如果您接受未定义的属性:

var clone = Object.assign({}, {a: 1, b: 2, c: 3}, {b: undefined});
这正是我正在寻找的,但稍微有点不同的实现方式: var cake = {...currentCake, requestorId: undefined };
2021-03-24 04:30:51
Object.assign 将指定的属性设为 undefined 并保存我的一天,谢谢!
2021-03-29 04:30:51
简单地删除属性是一种清晰而简单的方法。
2021-04-02 04:30:51
delete 的警告是它不是一成不变的操作。
2021-04-07 04:30:51
@JavidJamae 回到每个人都痴迷于一切不变性的时代
2021-04-10 04:30:51

我用这个 ESNext one liner

const obj = { a: 1, b: 2, c: 3, d: 4 }
const clone = (({ b, c, ...o }) => o)(obj) // remove b and c
console.log(clone)

这是一个很大的如果。我不相信我在共享代码库中的任何代码在某个时候不会有用户生成的文本输入......我不确定我什至不相信我永远不会忘记我的代码的内部并放置用户内容通过这。
2021-03-16 04:30:51
@totymedli:不是我的。出于可读性的考虑,我将随时采用标准 ES6 的一部分的句法形式,而不是魔法函数。
2021-03-21 04:30:51
@david.pfx 有一个缺点:可读性。尤其是当您将其与_.omit(obj, ['b', 'c']).
2021-03-28 04:30:51
而不是包装在数组中,map您可以执行以下操作:(({b, c, ...others}) => ({...others}))(obj)
2021-04-01 04:30:51
eval这里没人评论
2021-04-07 04:30:51

对于那些不会使用 ES6 的人,可以使用lodashunderscore

_.omit(x, 'b')

或者ramda

R.omit('b', x)
delete 更简洁——使用 lodash、下划线或 ramda 只与已经使用并了解它们的项目相关,否则这在 2018 年及以后越来越无关紧要。
2021-03-15 04:30:51
在这里使用omit不是更合乎逻辑吗? _.omit(x, 'b')
2021-03-19 04:30:51
谢谢@tibalt。用它更新了答案。
2021-03-19 04:30:51
@jimmont delete 已经在其他答案中提到了。不需要重复的答案,你不觉得吗?当然,它只与那些已经使用 lodash 或 ramda 的人相关。而且它也只与那些坚持使用 ES5 及更早版本的人有关,如本答案所述。
2021-03-20 04:30:51
@dashmug 我之前的评论是对方法(不是您的答案)的批评,在选择使用此答案中表示的方法时应注意这一点。如果我正在阅读答案,我会想要这些信息,这是添加我的评论和提及的原因delete
2021-04-07 04:30:51

添加到 Ilya Palkin 的答案:您甚至可以动态删除键:

const x = {a: 1, b: 2, c: 3, z:26};

const objectWithoutKey = (object, key) => {
  const {[key]: deletedKey, ...otherKeys} = object;
  return otherKeys;
}

console.log(objectWithoutKey(x, 'b')); // {a: 1, c: 3, z:26}
console.log(x); // {a: 1, b: 2, c: 3, z:26};

Babel REPL 中的演示

来源:

这很好,但是有没有办法避免未使用的 var deletedKey?并不是说它造成了任何问题,而是让 JSHint 抱怨,而且看起来很奇怪,因为我们真的没有使用它。
2021-03-27 04:30:51
var b = {a:44, b:7, c:1}; let {['a']:z, ...others} = b; console.log(z , others ); // logs: 44, {b:7, c:1}
2021-03-28 04:30:51
@JohnsonWong 对_不打算使用的变量使用哪个允许怎么样
2021-04-09 04:30:51