Cloning javascript object omitting one property [duplicate] - javascript

This question already has answers here:
Simplest way to copy JS object and filter out certain properties
(6 answers)
Remove key-value pair from JSON object
(7 answers)
Javascript - Removing object key not using delete
(2 answers)
Closed 3 years ago.
What's the best way in JavaScript for returning an object omitting just one or more properties?
I can assign a key to undefined and that works for sure, but what if want to completely get rid of that key?
function removeCKey() {
const obj = {a: 'a', b: 'b', c: 'c'}
return {
...obj,
c: undefined,
};
}
const myObj = removeCKey();
Also, I want to avoid creating an intermediate object where I use the spread operator like this
function removeCKey() {
const obj = {a: 'a', b: 'b', c: 'c'}
const {c, ...rest} = newObj
return rest;
}
const myObj = removeCKey();

You can use ES6 object destructuring assignment.
function removeKeys() {
const obj = {
a: 'a',
b: 'b',
c: 'c'
};
// extract property c in variable c
// and rest of the value into res
let { c, ...res } = obj;
return res;
}
console.log(removeKeys())

Just delete what you don't need:
function omit(obj, keys) {
const newObj = { ...obj }; // shallow copy...
keys.forEach(key => {
delete newObj[key]; // ... and `delete`.
});
return newObj;
}
omit({a: 'a', b: 'b', c: 'c'}, ['c']);
outputs
{ a: 'a', b: 'b' }

Related

js destructure and define field [duplicate]

This question already has an answer here:
object destructuring: how to use intermediate nested property
(1 answer)
Closed 12 days ago.
if I have the following object:
const obj = {
a: {
b: 'val',
},
};
and I want to destructure both a and b from the object, how would I go about doing it? I know this:
const { a: { b } } = obj;
but this doesn't let me access a. How can I also make a accessible in the code?
Just include it.
const obj = {
a: {
b: 'val',
},
};
const { a, a: { b } } = obj;
console.log(a);
console.log(b);

Destructure from dynamic key

Suppose I have some key-value object. I want to destructure dynamically from some key such that I can remove it and just get the remaining items in a new object.
const omit = (obj, key) => {
const { [key], ...rest } = obj // Syntax error
return rest
}
omit({ b: 1, c: 2, d: 3 }, 'd')
// desired output { b: 1, c: 2 }
Is there a way to do that?
Disclaimer: I know there are lots of workarounds but would like to do it with destructuring.
In order to destructure on a dynamic key you will need to provide an alias for JS to bind that value to.
Firefox even gives you a helpful error message here:
const omit = (obj, key) => {
const { [key]: _, ...rest } = obj
// CHANGE -----^
return rest
}
console.log(omit({ b: 1, c: 2, d: 3 }, 'd'))
You can rename the variables when destructuring, and the left side (preexisting name) can be in brackets like you want.
let {[key]: omitted, ...rest} = a;

Javascript (ES6 + Lodash) merge source object with another updating only common properties, deeply

I have to deeply update an object with a provided one
, keeping only the properties/paths found in the source object.
I tried Lodash.merge, but it merges all the properties of the second object, I want to merge only the properties found in the source object.
Here is an example:
const ob1 = {
a1: {
b1: 2
},
a2: 5
}
const obj2 = {
a1: {
b1: 4,
b2: 9
},
a3: 6
}
expected result = {
a1: {
b1: 4
},
a2: 5
}
I'd like the simplest solution with es6 or lodash utils.
Any ideas? Thanks!
If you want a custom merge strategy, perhaps you can write your own recursive function. In the recursive function, you basically pass in your target and your source. Based on your question, the target will be obj1 and the source will be obj2.
Your logic is that:
If obj1 does not contain a key that is in obj2, we keep the key-value pair from the obj1, the source
If obj1 contains a key that is obj2, then:
If they are simply non-objects, we allow obj2 value to override obj1 value
If they are both objects, then we call the same recursive function again
See proof-of-concept below:
const obj1 = {
a1: {
b1: 2
},
a2: 5
}
const obj2 = {
a1: {
b1: 4,
b2: 9
},
a3: 6
}
function smartMerge(target, source) {
const o = {};
// Iterate throught all keys in your target
for(let k in target) {
// If a matching key is found in source
if (k in source) {
// If they are both objects, then we run recurisve merge logic
if (typeof target[k] === 'object' && typeof source[k] === 'object') {
o[k] = smartMerge(target[k], source[k]);
}
// Otherwise, we let the source override the value
else {
o[k] = source[k];
}
}
// If no matching key is found, we keep the target value
else {
o[k] = target[k];
}
}
return o;
}
const result = smartMerge(obj1, obj2);
/* Expected:
{
a1: {
b1: 4
},
a2: 5
}
*/
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>

Take array of strings as property accessor

I would like to get a value from an object with accessing it with array of strings.
Static example: Input: ['a','b','c'] Output: function (t) { t.a.b.c; }
I would like to make a function that resolves the problem for any array.
function (state) {
let value = state;
for (let i = 0; i < propNames.length; i++) {
value = value[propNames[i]];
}
return value;
};
Other solution is a generator for a function by reducer.
These are working. I would like to know if there is any other faster solutions that I didn't think of.
You can test here the algorithms. There is a place where your code can be added.
A fast way to do it is to iterate over the properties and access the inner objects sequentially, you can do this using Array.reduce() or a for loop:
const get = (obj, props) => props.reduce((out, p) => out && out[p] || undefined, obj);
const obj = { a: { b: { c: 5 } } };
console.log(get(obj, ['a', 'b', 'c']));
console.log(get(obj, ['a', 'b', 'c', 'd', 'e']));
Or, you could evaluate the expression using eval(), however, this is probably the slowest way to do it, I do not recomment it:
const get = (obj, props) => {
try {
return eval(`obj.${props.join('.')}`);
} catch {
return undefined;
}
}
const obj = { a: { b: { c: 5 } } };
console.log(get(obj, ['a', 'b', 'c']));
console.log(get(obj, ['a', 'b', 'c', 'd', 'e']));

reconstruct partial deconstructed object es6

I am looking for the most concise way to have a new object out of the fields of the deconstructed one.
let obj = {
a: 1,
b: 2,
c: null
}
Currently I have:
let {a, c} = obj;
let data = {a, c}
What I wished I would be having:
let data = {a, c} = obj;
// but data actually becomes {a, b, c}
// and not {a, b} as I wished it to be.
Although your code looks fine may be if your task consists in cherrypicking keys and put it in another object destructuring is not the best approach:
const object = { a: 5, b: 6, c: 7 };
const picked = (({ a, c }) => ({ a, c }))(object);
console.log(picked)
You can define a function that will provide the destructured object as the return value, and assign the call to data:
const obj = {
a: 1,
b: 2,
c: null
}
const partial = ({ a, c }) => ({ a, c })
const data = partial(obj)
console.log(data)
Unfortunately this isn't possible in one line without some setup, but the setup is worthwhile if you are creating the same partial object a lot of places in your source.
Rather than rely on destructuring for this, you can implement a version of the commonly found "pick" function, that accepts as input an object and an array of keys to pull out of that object:
function pick(obj, keys) {
return keys.reduce((memo, key) => {
memo[key] = obj[key];
return memo;
}, {});
}
const obj = { a: 1, b: 2, c: 3 }
const data = pick(obj, ['a', 'b']);
console.log(data); // { a: 1, b: 2}
Normally I would consider performance less important than readability, which is highly subjective. But in this case, both the pick solution above and the one-liners are orders of magnitude slower than your original two-liner, though pick wins out over the one-liner by a comparatively small margin: https://jsperf.com/testaagwt14124oih1oij

Categories