502

我有一个扁平的 JS 对象:

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

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

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

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

4

28 回答 28

691

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

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

它将被编译成:

"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"]);
于 2016-01-10T19:54:56.313 回答
206
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});
于 2016-01-09T21:07:55.650 回答
161

我用这个 ESNext 一个班轮

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

于 2018-11-23T08:55:12.803 回答
93

不会使用 ES6 的可以使用lodashunderscore.

_.omit(x, 'b')

ramda

R.omit('b', x)
于 2017-01-13T04:16:04.347 回答
89

要添加到 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 中的演示

资源:

于 2016-11-20T00:55:14.943 回答
30

您可以为它编写一个简单的辅助函数。Lodash 有一个类似的同名函数:省略

function omit(obj, omitKey) {
  return Object.keys(obj).reduce((result, key) => {
    if(key !== omitKey) {
       result[key] = obj[key];
    }
    return result;
  }, {});
}

omit({a: 1, b: 2, c: 3}, 'c')  // {a: 1, b: 2}

另外,请注意,它比 Object.assign 快,然后删除:http: //jsperf.com/omit-key

于 2016-01-10T12:07:21.737 回答
19

这是一个省略我认为尚未提及的动态键的选项:

const obj = { 1: 1, 2: 2, 3: 3, 4: 4 };
const removeMe = 1;

const { [removeMe]: removedKey, ...newObj } = obj;

removeMe别名为removedKey并被忽略。newObj变成{ 2: 2, 3: 3, 4: 4 }. 请注意,删除的键不存在,该值不只是设置为undefined.

于 2019-10-02T17:31:36.840 回答
17

也许是这样的:

var copy = Object.assign({}, {a: 1, b: 2, c: 3})
delete copy.c;

这够好吗?或者实际上不能c被复制?

于 2016-01-09T21:06:51.383 回答
14

使用对象解构

const omit = (prop, { [prop]: _, ...rest }) => rest;
const obj = { a: 1, b: 2, c: 3 };
const objWithoutA = omit('a', obj);
console.log(objWithoutA); // {b: 2, c: 3}

于 2019-03-23T00:14:06.797 回答
11

这个怎么样:

let clone = Object.assign({}, value);
delete clone.unwantedKey;
于 2020-01-21T16:42:44.460 回答
6

我最近以一种非常简单的方式做到了:

const obj = {a: 1, b: 2, ..., z:26};

只需使用扩展运算符来分隔不需要的属性:

const {b, ...rest} = obj;

...和​​object.assign只占用“其余”部分:

const newObj = Object.assign({}, {...rest});
于 2019-02-27T10:26:43.647 回答
6

嘿,当您尝试复制对象然后删除属性时,您似乎遇到了引用问题。您必须在某个地方分配原始变量,以便 javascript 生成一个新值。

我使用的简单技巧(可能很可怕)是这个

var obj = {"key1":"value1","key2":"value2","key3":"value3"};

// assign it as a new variable for javascript to cache
var copy = JSON.stringify(obj);
// reconstitute as an object
copy = JSON.parse(copy);
// now you can safely run delete on the copy with completely new values
delete copy.key2

console.log(obj)
// output: {key1: "value1", key2: "value2", key3: "value3"}
console.log(copy)
// output: {key1: "value1", key3: "value3"}
于 2018-06-07T13:44:57.757 回答
6

您也可以使用扩展运算符来执行此操作

const source = { a: 1, b: 2, c: 3, z: 26 }
const copy = { ...source, ...{ b: undefined } } // { a: 1, c: 3, z: 26 }
于 2018-09-12T10:15:13.127 回答
4

上面使用结构化的解决方案确实受到这样一个事实的影响,即你有一个 used 变量,如果你使用它,这可能会引起 ESLint 的抱怨。

所以这是我的解决方案:

const src = { a: 1, b: 2 }
const result = Object.keys(src)
  .reduce((acc, k) => k === 'b' ? acc : { ...acc, [k]: src[k] }, {})

在大多数平台上(IE 除外,除非使用 Babel),您还可以执行以下操作:

const src = { a: 1, b: 2 }
const result = Object.fromEntries(
  Object.entries(src).filter(k => k !== 'b'))
于 2019-06-06T17:15:53.573 回答
4

我是通过这种方式完成的,以我的 Redux reducer 为例:

 const clone = { ...state };
 delete clone[action.id];
 return clone;

换句话说:

const clone = { ...originalObject } // note: original object is not altered
delete clone[unwantedKey]           // or use clone.unwantedKey or any other applicable syntax
return clone                        // the original object without the unwanted key
于 2019-04-28T22:31:42.697 回答
3
const x = {obj1: 1, pass: 2, obj2: 3, obj3:26};

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

console.log(objectWithoutKey(x, 'pass'));
于 2020-05-11T11:33:58.483 回答
3

如果您正在处理一个巨大的变量,您不想复制它然后删除它,因为这会效率低下。

一个带有 hasOwnProperty 检查的简单 for 循环应该可以工作,而且它更能适应未来的需求:

for(var key in someObject) {
        if(someObject.hasOwnProperty(key) && key != 'undesiredkey') {
                copyOfObject[key] = someObject[key];
        }
}
于 2017-08-10T13:40:30.520 回答
3

Lodash省略

let source = //{a: 1, b: 2, c: 3, ..., z:26}
let copySansProperty = _.omit(source, 'b');
// {a: 1, c: 3, ..., z:26}
于 2017-10-05T15:44:28.970 回答
3

那这个呢?我从来没有发现这种模式,但我只是想排除一个或多个属性,而不需要创建额外的对象。这似乎可以完成这项工作,但有一些我看不到的副作用。肯定不是很可读。

const postData = {
   token: 'secret-token',
   publicKey: 'public is safe',
   somethingElse: true,
};

const a = {
   ...(({token, ...rest} = postData) => (rest))(),
}

/**
a: {
   publicKey: 'public is safe',
   somethingElse: true,
}
*/
于 2019-03-19T12:08:27.133 回答
2

如果你使用Ramda,你可以使用它的omitclone函数来对你的对象进行深度克隆并省略不必要的字段。

var object = {a: 1, b: 2, c: 3, y:25, z:26};
R.clone(R.omit(["z", "y"], object));
于 2021-02-05T07:35:54.127 回答
1

我不确切知道你想用它做什么,所以我不确定这是否适合你,但我只是做了以下事情,它适用于我的用例:

const newObj ={...obj, [key]: undefined}
于 2020-12-27T16:15:13.830 回答
1

如果您使用打字稿,删除关键字解决方案将引发编译错误,因为它违反了您实例化的对象的合同。并且 ES6 扩展运算符解决方案 ( const {x, ...keys} = object) 可能会根据您在项目中使用的 linting 配置引发错误,因为x未使用该变量。所以我想出了这个解决方案:

const cloneObject = Object.entries(originalObject)
    .filter(entry => entry[0] !== 'keyToRemove')
    .reduce((acc, keyValueTuple) => ({ ...acc, [keyValueTuple[0]]: keyValueTuple[1] }), {});

它使用Object.entries方法(获取原始对象的键/值对数组)和数组方法filterreduce的组合来解决问题。它看起来很冗长,但我认为有一个单行可链接的解决方案很好。

于 2021-05-25T21:24:55.827 回答
0

我有一个object我想在使用它的方法后删除的。这对我有用。


/* Sample data */
let items = [
  {
    name: 'John',
    doc: {
      set: async (item) => {/*...sets docs on remote server*/}
    }
  },{
    name: 'Mary',
    doc: {
      set: async (item) => {/*...sets docs on remote server*/}
    }
  },{
    name: 'Jack',
    doc: {
      set: async (item) => {/*...sets docs on remote server*/}
    }
  }
]

/* mapping to promises */
const promises = items.map(({doc, ...item}) => doc.set(item)); 
// utilized doc and utilized `rest` of the items :)


祝你好运 :)

于 2020-07-13T01:37:27.937 回答
0

这是一个 Typescript 方法来做到这一点。需要 2 个参数,对象和包含要删除的键的字符串数组:

removeKeys(object: { [key: string]: any }, keys: string[]): { [key: string]: any } {
  const ret: { [key: string]: any } = {};

  for (const key in object) {
    if (!keys.includes(key)) {
      ret[key] = object[key];
    }
  }

  return ret;
}
于 2021-11-19T08:17:45.297 回答
0

使用 lodash 干净快速,使用此解决方案,您可以删除多个键,并且无需更改原始对象。这在不同的情况下更具可扩展性和可用性:

import * as _ from 'lodash';

function cloneAndRemove(
    removeTheseKeys: string[],
    cloneObject: any,
): object | never {
    const temp = _.cloneDeep(cloneObject);
    removeTheseKeys.forEach((key) => {
        delete temp[key];
    });

    return temp;
}

export { cloneAndRemove };
于 2021-08-09T14:19:53.837 回答
0

我有一个名为:带有一些键的选项

  let options = {       
        userDn: 'somePropertyValue',
        username: 'someValue',
        userSearchBase: 'someValue',
        usernameAttribute: 'uid',
        userPassword: 'someValue'
    }

我想记录所有对象 excelp userPassword 属性,因为我正在测试一些东西,我正在使用以下代码:

console.log(Object.keys(options).map(x => x + ': ' + (x === "userPassword" ? '---' : options[x])));

如果要使其动态化,只需创建一个函数,而不是显式放置userPassword,您可以放置​​要排除的属性的值

于 2020-10-22T09:42:49.477 回答
0

这是我在 Typescript 上的两分钱,略微源自@Paul 的回答,而是使用reduce

function objectWithoutKey(object: object, keys: string[]) {
    return keys.reduce((previousValue, currentValue) => {
        // @ts-ignore
        const {[currentValue]: undefined, ...clean} = previousValue;
        return clean
    }, object)
}

// usage
console.log(objectWithoutKey({a: 1, b: 2, c: 3}, ['a', 'b']))
于 2020-08-16T19:21:28.577 回答
-1

使用 loadash deepclone 功能您可以执行以下操作:

const _obj = _.cloneDeep(obj);
delete _obj.key;

首先将整个对象克隆到新对象中,然后从克隆对象中删除所需的键,以免影响原始对象。

于 2021-03-05T19:12:15.307 回答