ama*_*ann 77 javascript immutability
在不改变原始对象的情况下从特定键的对象中删除值的好方法和简短方法是什么?
我想做点什么:
let o = {firstname: 'Jane', lastname: 'Doe'};
let o2 = doSomething(o, 'lastname');
console.log(o.lastname); // 'Doe'
console.log(o2.lastname); // undefined
Run Code Online (Sandbox Code Playgroud)
我知道有很多不可变的库用于这样的任务,但我想在没有库的情况下离开.但要做到这一点,一个要求是有一个简单而简短的方法可以在整个代码中使用,而不会将方法作为效用函数抽象出来.
例如,为了添加值,我执行以下操作:
let o2 = {...o1, age: 31};
这很简单,易于记忆,不需要实用功能.
是否有类似的东西去除值?ES6非常受欢迎.
非常感谢你!
Leo*_*tny 174
您可以通过棘手的Destructuring赋值从对象中删除属性:
const doSomething = (obj, prop) => {
let {[prop]: omit, ...res} = obj
return res
}
Run Code Online (Sandbox Code Playgroud)
但是,如果要删除的属性名称是静态的,那么您可以使用简单的单行删除它:
let {lastname, ...o2} = o
Run Code Online (Sandbox Code Playgroud)
最简单的方法就是或者你可以在变异之前克隆你的对象:
const doSomething = (obj, prop) => {
let res = Object.assign({}, obj)
delete res[prop]
return res
}
Run Code Online (Sandbox Code Playgroud)
另外,您可以使用omit
从功能lodash
实用程序库:
let o2 = _.omit(o, 'lastname')
Run Code Online (Sandbox Code Playgroud)
它作为lodash包的一部分提供,或作为独立的lodash.omit包提供.
sen*_*bon 17
使用ES7对象解构:
const myObject = {
a: 1,
b: 2,
c: 3
};
const { a, ...noA } = myObject;
console.log(noA); // => { b: 2, c: 3 }
Run Code Online (Sandbox Code Playgroud)
pun*_*sta 14
一线解决方案
const removeKey = (key, {[key]: _, ...rest}) => rest;
Run Code Online (Sandbox Code Playgroud)
正如上面评论中所建议的,如果您想扩展它以从您的object
I like to use 中删除多个项目filter
。和reduce
例如
const o = {
"firstname": "Jane",
"lastname": "Doe",
"middlename": "Kate",
"age": 23,
"_id": "599ad9f8ebe5183011f70835",
"index": 0,
"guid": "1dbb6a4e-f82d-4e32-bb4c-15ed783c70ca",
"isActive": true,
"balance": "$1,510.89",
"picture": "http://placehold.it/32x32",
"eyeColor": "green",
"registered": "2014-08-17T09:21:18 -10:00",
"tags": [
"consequat",
"ut",
"qui",
"nulla",
"do",
"sunt",
"anim"
]
};
const removeItems = ['balance', 'picture', 'tags']
console.log(formatObj(o, removeItems))
function formatObj(obj, removeItems) {
return {
...Object.keys(obj)
.filter(item => !isInArray(item, removeItems))
.reduce((newObj, item) => {
return {
...newObj, [item]: obj[item]
}
}, {})
}
}
function isInArray(value, array) {
return array.indexOf(value) > -1;
}
Run Code Online (Sandbox Code Playgroud)
添加一些香料,带来性能。检查这个线程波纹管
https://github.com/googleapis/google-api-nodejs-client/issues/375
删除操作符的使用对 V8 隐藏类模式有性能负面影响。一般来说,建议不要使用它。
或者,要删除对象自己的可枚举属性,我们可以创建一个没有这些属性的新对象副本(例如使用 lodash):
_.omit(o, 'prop', 'prop2')
或者甚至将属性值定义为 null 或 undefined(在序列化为 JSON 时会隐式忽略):
o.prop = 未定义
你也可以使用破坏性的方式
const {remov1, remov2, ...new} = old;
old = new;
Run Code Online (Sandbox Code Playgroud)
还有一个更实用的例子:
this._volumes[this._minCandle] = undefined;
{
const {[this._minCandle]: remove, ...rest} = this._volumes;
this._volumes = rest;
}
Run Code Online (Sandbox Code Playgroud)
如您所见,您可以将[somePropsVarForDynamicName]: scopeVarName
语法用于动态名称。您可以将所有内容放在括号中(新块),以便其余部分在它之后被垃圾收集。
执行:
或者我们可以使用一些功能,例如
function deleteProps(obj, props) {
if (!Array.isArray(props)) props = [props];
return Object.keys(obj).reduce((newObj, prop) => {
if (!props.includes(prop)) {
newObj[prop] = obj[prop];
}
return newObj;
}, {});
}
Run Code Online (Sandbox Code Playgroud)
打字稿
const {remov1, remov2, ...new} = old;
old = new;
Run Code Online (Sandbox Code Playgroud)
用法:
let a = {propH: 'hi', propB: 'bye', propO: 'ok'};
a = deleteProps(a, 'propB');
// or
a = deleteProps(a, ['propB', 'propO']);
Run Code Online (Sandbox Code Playgroud)
这样就创建了一个新对象。并且保持了对象的快速属性。这可能很重要或很重要。如果映射和对象会被多次访问。
关联undefined
也是一个很好的方式。当你买得起的时候。对于键,您也可以检查值。例如,要获取所有活动键,您可以执行以下操作:
const allActiveKeys = Object.keys(myObj).filter(k => myObj[k] !== undefined);
//or
const allActiveKeys = Object.keys(myObj).filter(k => myObj[k]); // if any false evaluated value is to be stripped.
Run Code Online (Sandbox Code Playgroud)
未定义虽然不适合大列表。或者随着时间的推移,有许多道具进入。由于内存使用量将不断增长并且永远不会被清理。所以这取决于用途。只是创建一个新对象似乎是个好方法。
然后Premature optimization is the root of all evil
就会开始。所以你需要知道权衡。什么是需要的,什么不是。
它已从版本 5 中删除。您在 repo 中找不到它。这里有一个谈论它的问题。
https://github.com/lodash/lodash/issues/2930
你可以检查这是一个很好的阅读https://v8.dev/blog/fast-properties