如何克隆除一个键之外的 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(?
JavaScript 中有一个可以使用的解构赋值语法
let obj = {a: 1, b: 2, c: 3, z:26};
let {b, ...rest} = obj;
// skips the "Unused variable" warning
let {b: _, ...rest} = obj;
// removes property based on the dynamic key
const dynamicKey = "b";
let {[dynamicKey]: _, ...rest} = obj;
现代浏览器已经开箱即用地支持它。参见:JavaScript 运算符:解构赋值:Rest in Object
对于旧的浏览器版本,有一个选项可以使用 Babel 来支持解构赋值。它将被转换为:
"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"]);
我使用这个 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)
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});
对于那些不能使用 ES6 的人,您可以使用 lodash
或 underscore
。
_.omit(x, 'b')
或者ramda
.
R.omit('b', x)
补充一下伊利亚·帕尔金的答案: 您甚至可以动态删除键:
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};
巴别塔 REPL 中的演示
源:
- https://twitter.com/ydkjs/status/699845396084846592
您可以为其编写一个简单的帮助程序函数。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
这是一个用于省略动态键的选项,我认为尚未提及:
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
。
也许是这样的:
var copy = Object.assign({}, {a: 1, b: 2, c: 3})
delete copy.c;
这够好吗?还是c
真的不能被复制?
使用对象解构
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}
当您尝试复制对象然后删除属性时,您似乎遇到了引用问题。在某个地方,你必须分配原始变量,以便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 }
这个呢?我从来没有发现过这种模式,但我只是试图排除一个或多个属性,而无需创建额外的对象。这似乎可以完成这项工作,但有一些副作用我看不到。肯定不是很好读。
const postData = {
token: 'secret-token',
publicKey: 'public is safe',
somethingElse: true,
};
const a = {
...(({token, ...rest} = postData) => (rest))(),
}
/**
a: {
publicKey: 'public is safe',
somethingElse: true,
}
*/
Lodash 省略
let source = //{a: 1, b: 2, c: 3, ..., z:26}
let copySansProperty = _.omit(source, 'b');
// {a: 1, c: 3, ..., z:26}
我是这样完成的,作为我的 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] }, {})
在大多数平台上(除非使用 Babel,IE 除外(,您还可以执行以下操作:
const src = { a: 1, b: 2 }
const result = Object.fromEntries(
Object.entries(src).filter(k => k !== 'b'))
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'));
我在这里使用对象解构。我已将密码分成变量,其余变量包含除密码之外的所有对象属性和值。注意:其余不是固定关键字,在这里您可以相应地命名它
const obj = {name:"john", password:"Abcds12@", id:"125455"}
const {password,...rest} = obj;
console.log(rest);
如果你正在处理一个巨大的变量,你不想复制它然后删除它,因为这会效率低下。
带有hasOwnProperty检查的简单for循环应该可以工作,并且它更适合未来的需求:
for(var key in someObject) {
if(someObject.hasOwnProperty(key) && key != 'undesiredkey') {
copyOfObject[key] = someObject[key];
}
}
我不知道你想用它做什么,所以我不确定这是否适合你,但我只是做了以下工作,它适用于我的用例:
const newObj ={...obj, [key]: undefined}
如果您使用的是打字稿,则 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 方法(获取原始对象的键/值对数组(和数组方法过滤和归约的组合来解决问题。它看起来很冗长,但我认为有一个单行可链接的解决方案很好。
在 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']))
我有一个名为:带有一些键的选项
let options = {
userDn: 'somePropertyValue',
username: 'someValue',
userSearchBase: 'someValue',
usernameAttribute: 'uid',
userPassword: 'someValue'
}
我想记录所有对象 excelp 用户密码属性,因为我正在测试某些东西,我正在使用以下代码:
console.log(Object.keys(options).map(x => x + ': ' + (x === "userPassword" ? '---' : options[x])));
如果你想让它动态化,只需创建一个函数,而不是显式放置userPassword,你可以放置你想要排除的属性的值
使用 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;
}
您可以使用 lodash 库来实现此目的(如果您需要在项目中处理大量数组/对象数组/对象
(。使用 lodash 深度克隆函数 您可以执行以下操作:
const _obj = _.cloneDeep(obj);
delete _obj.key;
首先将整个对象克隆到新对象中,然后从克隆的对象中删除所需的键,以便原始对象不会受到影响。
- 面向对象JavaScript中的私有函数
- 对象 Javascript 中的标签无效 - 想要添加事件列表器
- 将字符串转换为对象 javascript/jquery
- 正在检查对象javascript中是否存在嵌套属性
- 时间-日期对象JavaScript getUTCMilliseconds
- 仅在对象(javascript)中解析值
- 使用对象(JavaScript或jQuery)填充选择下拉列表
- 引用另一个对象javascript中的对象
- 如何删除列表中的对象?Javascript nodejs和下划线
- 无法从日期对象javascript获取日期和月份
- 如何在if语句中使用对象-Javascript
- 对象javascript错误
- 对象Javascript的少数实例
- 位置对象Javascript
- 将字符串传递到对象javascript中
- 获取对象Javascript或jQuery的最后一个值
- 鼠标接近对象Javascript
- 这个mixins代码是书中的错误吗;面向对象JavaScript的原理”;
- 使用闭包编译器编写更好的面向对象JavaScript完整示例代码
- 访问对象javascript数组中的对象属性值