除了一个键,我如何克隆一个 JavaScript 对象?
How can I clone a JavaScript object except for one key?
我有一个平面 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 有一个类似的同名函数:omit
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
如果您使用 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"]);
添加 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
或underscore
。
_.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];
}
}
lodash omit
let source = //{a: 1, b: 2, c: 3, ..., z:26}
let copySansProperty = _.omit(source, 'b');
// {a: 1, c: 3, ..., z:26}
嘿,当您尝试复制对象然后删除 属性 时,您似乎 运行 遇到了引用问题。在某处你必须分配原始变量,所以 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"}
您也可以使用展开运算符来做到这一点
const source = { a: 1, b: 2, c: 3, z: 26 }
const copy = { ...source, ...{ b: undefined } } // { a: 1, c: 3, z: 26 }
我用这个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)
我最近用这种非常简单的方法做到了:
const obj = {a: 1, b: 2, ..., z:26};
只需使用 展开运算符 来分隔不需要的 属性:
const {b, ...rest} = obj;
...和 object.assign 只取 'rest' 部分:
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;
const obj = { a: 1, b: 2, c: 3 };
const objWithoutA = omit('a', obj);
console.log(objWithoutA); // {b: 2, c: 3}
我是这样完成的,以我的 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
上面使用结构化的解决方案确实存在一个使用过的变量的问题,如果您正在使用它,可能会引起 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 }
。请注意,删除的键不存在,值不只是设置为 undefined
.
这个怎么样:
let clone = Object.assign({}, value);
delete clone.unwantedKey;
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'));
我有一个 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 :)
祝你好运:)
这是我在 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']))
我有一个名为:options 和一些键的对象
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]: undefined}
如果您使用 Ramda you can use its omit and clone 函数对您的对象进行深度克隆并省略不必要的字段。
var object = {a: 1, b: 2, c: 3, y:25, z:26};
R.clone(R.omit(["z", "y"], object));
使用 loadash 深度克隆功能您可以:
const _obj = _.cloneDeep(obj);
delete _obj.key;
首先将整个对象克隆到新对象中,然后从克隆对象中删除所需的键,这样原始对象就不会受到影响。
如果您使用 typescript,delete 关键字解决方案将引发编译错误,因为它破坏了您实例化的对象的契约。 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 method (to get an array of key/value pairs of the original object) and the array methods filter and reduce的组合解决了这个问题。它看起来很冗长,但我认为有一个单行可链接的解决方案很好。
使用 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 };
这是执行此操作的 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;
}
我有一个平面 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 有一个类似的同名函数:omit
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
如果您使用 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"]);
添加 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
或underscore
。
_.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];
}
}
lodash omit
let source = //{a: 1, b: 2, c: 3, ..., z:26}
let copySansProperty = _.omit(source, 'b');
// {a: 1, c: 3, ..., z:26}
嘿,当您尝试复制对象然后删除 属性 时,您似乎 运行 遇到了引用问题。在某处你必须分配原始变量,所以 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"}
您也可以使用展开运算符来做到这一点
const source = { a: 1, b: 2, c: 3, z: 26 }
const copy = { ...source, ...{ b: undefined } } // { a: 1, c: 3, z: 26 }
我用这个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)
我最近用这种非常简单的方法做到了:
const obj = {a: 1, b: 2, ..., z:26};
只需使用 展开运算符 来分隔不需要的 属性:
const {b, ...rest} = obj;
...和 object.assign 只取 'rest' 部分:
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;
const obj = { a: 1, b: 2, c: 3 };
const objWithoutA = omit('a', obj);
console.log(objWithoutA); // {b: 2, c: 3}
我是这样完成的,以我的 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
上面使用结构化的解决方案确实存在一个使用过的变量的问题,如果您正在使用它,可能会引起 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 }
。请注意,删除的键不存在,值不只是设置为 undefined
.
这个怎么样:
let clone = Object.assign({}, value);
delete clone.unwantedKey;
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'));
我有一个 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 :)
祝你好运:)
这是我在 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']))
我有一个名为:options 和一些键的对象
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]: undefined}
如果您使用 Ramda you can use its omit and clone 函数对您的对象进行深度克隆并省略不必要的字段。
var object = {a: 1, b: 2, c: 3, y:25, z:26};
R.clone(R.omit(["z", "y"], object));
使用 loadash 深度克隆功能您可以:
const _obj = _.cloneDeep(obj);
delete _obj.key;
首先将整个对象克隆到新对象中,然后从克隆对象中删除所需的键,这样原始对象就不会受到影响。
如果您使用 typescript,delete 关键字解决方案将引发编译错误,因为它破坏了您实例化的对象的契约。 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 method (to get an array of key/value pairs of the original object) and the array methods filter and reduce的组合解决了这个问题。它看起来很冗长,但我认为有一个单行可链接的解决方案很好。
使用 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 };
这是执行此操作的 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;
}