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

除了一个键外,如何克隆JavaScript对象?,javascript,ecmascript-6,ecmascript-harmony,ecmascript-2016,Javascript,Ecmascript 6,Ecmascript Harmony,Ecmascript 2016,我有一个平面JS对象: {a: 1, b: 2, c: 3, ..., z:26} 我要克隆除一个元素之外的对象: {a: 1, c: 3, ..., z:26} 最简单的方法是什么(如果可能,更喜欢使用es6/7)?可能是这样的: var copy = Object.assign({}, {a: 1, b: 2, c: 3}) delete copy.c; 这够好吗?或者c不能被复制 var clone = Object.assign({}, {a: 1, b: 2, c: 3}); d

我有一个平面JS对象:

{a: 1, b: 2, c: 3, ..., z:26}
我要克隆除一个元素之外的对象:

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

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

可能是这样的:

var copy = Object.assign({}, {a: 1, b: 2, c: 3})
delete copy.c;
这够好吗?或者
c
不能被复制

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});

您可以为它编写一个简单的助手函数。Lodash具有相同名称的类似功能:

另外,请注意,它比Object.assign和delete then快:

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

并分为:


要补充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};

资料来源:


对于不能使用ES6的用户,您可以使用
lodash
下划线

_.omit(x, 'b')
ramda

R.omit('b', x)

如果您处理的是一个巨大的变量,您不希望复制它然后删除它,因为这样做效率很低

带有hasOwnProperty检查的简单for循环应该可以工作,并且它更适合未来的需要:

for(var key in someObject) {
        if(someObject.hasOwnProperty(key) && key != 'undesiredkey') {
                copyOfObject[key] = someObject[key];
        }
}
洛达斯


当您尝试复制对象然后删除属性时,似乎遇到了引用问题。在某些地方,您必须分配基本变量,以便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"}

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

const source = { a: 1, b: 2, c: 3, z: 26 }
const copy = { ...source, ...{ b: undefined } } // { a: 1, c: 3, z: 26 }

下一个班轮我用这个

constobj={a:1,b:2,c:3,d:4}
const clone=({b,c,…o})=>o(obj)//删除b和c

console.log(clone)
我最近用了一种非常简单的方法:

const obj = {a: 1, b: 2, ..., z:26};
只需使用spread运算符来分离不需要的属性:

const {b, ...rest} = obj;
…和object.assign仅获取“剩余”部分:

const newObj = Object.assign({}, {...rest});
这个怎么样? 我从未发现这种模式,但我只是试图排除一个或多个属性,而不需要创建额外的对象。这似乎起到了作用,但有些副作用我看不出来。当然,它的可读性不是很强

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

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

/**
a: {
   publicKey: 'public is safe',
   somethingElse: true,
}
*/

使用对象分解

const-omit=(prop,{[prop]:,…rest})=>rest;
常量obj={a:1,b:2,c:3};
const objwithout a=省略('a',obj);

console.log(objWithoutA);//{b:2,c:3}
我是这样完成的,作为我的Redux reducer的一个例子:

const clone={…state};
删除克隆[action.id];
返回克隆;
换言之:

const clone={…originalObject}//注意:原始对象未更改
删除clone[unwantedKey]//或使用clone.unwantedKey或任何其他适用语法
返回克隆//没有不需要的键的原始对象

上述使用结构化的解决方案确实存在一个问题,即您使用了一个变量,如果您使用该变量,可能会引起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'))

这里有一个我认为还没有提到的省略动态键的选项:

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}
。请注意,删除的键不存在,该值不只是设置为
未定义

如何:

let clone = Object.assign({}, value);
delete clone.unwantedKey;

我有一个
对象
,我想在使用它的方法后删除它。这就是我的工作


/*样本数据*/
让项目=[
{
姓名:'约翰',
文件:{
set:async(item)=>{/*…设置远程服务器上的文档*/}
}
},{
姓名:'玛丽',
文件:{
set:async(item)=>{/*…设置远程服务器上的文档*/}
}
},{
名字:“杰克”,
文件:{
set:async(item)=>{/*…设置远程服务器上的文档*/}
}
}
]
/*映射到承诺*/
const promises=items.map(({doc,…item})=>doc.set(item));
//已使用的单据和已使用的“剩余”项目:)

祝你好运:)

这是我的两分钱,在打字稿上,从@Paul的答案中略作衍生,使用reduce代替

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

  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,您可以放置要排除的属性的值

我不知道您到底想用它做什么,所以我不确定这是否适用于您,但我只是做了以下操作,它适用于我的用例:

const newObj={…obj[key]:未定义}
如果使用,则可以使用其和函数对对象进行深度克隆,并省略不必要的字段

var object = {a: 1, b: 2, c: 3, y:25, z:26};
R.clone(R.omit(["z", "y"], object));

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

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

首先将整个对象克隆到新对象中,然后从克隆的对象中删除所需的键,这样原始对象就不会受到影响。

如果使用typescript,delete关键字解决方案将抛出编译错误,因为它破坏了实例化对象的约定。ES6 spread运算符解决方案(
const{x,…keys}=object
)可能会抛出错误,具体取决于您在项目中使用的linting配置,因为未使用
x
变量。所以我提出了这个解决方案:

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

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

如果你为未使用的变量筛选代码,这将导致“未使用的变量'b.”警告。如果你有
let x=[{a:1,b:2,c:3,z:26},{a:5,b:6,c:7,z:455}],语法会是什么样子
@RossAllen在v3.15.0中添加了一个选项(2017年2月3日)
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']))
  let options = {       
        userDn: 'somePropertyValue',
        username: 'someValue',
        userSearchBase: 'someValue',
        usernameAttribute: 'uid',
        userPassword: 'someValue'
    }
console.log(Object.keys(options).map(x => x + ': ' + (x === "userPassword" ? '---' : options[x])));
var object = {a: 1, b: 2, c: 3, y:25, z:26};
R.clone(R.omit(["z", "y"], object));
const _obj = _.cloneDeep(obj);
delete _obj.key;
const cloneObject = Object.entries(originalObject)
    .filter(entry => entry[0] !== 'keyToRemove')
    .reduce((acc, keyValueTuple) => ({ ...acc, [keyValueTuple[0]]: keyValueTuple[1] }), {});