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);
Related
const a = {
b: {
c: 'Hi!'
}
};
const { b: { c } } = a;
Is it possible rename b in this case? I want get c and also rename b.
You could destructure with a renaming and take the same property for destructuring.
const a = { b: { c: 'Hi!' } };
const { b: formerB, b: { c } } = a;
console.log(formerB)
console.log(c);
You can destructure the same property multiple times, onto different targets:
const { b: {c}, b: d } = a;
This assigns a.b.c to c and a.b to d.
If function parameter is empty is there a way to pass ...rest of the destructured values to that parameter with spread operator?
For an example:
const obj = {
/* param: {
a: 2,
b: 3
}, */
c: 1,
d: 3
}
const fun = ({ param = ...rest}) => {
console.log(param);
};
fun(obj);
In this case param is "undefined" and i would like to get the rest of the obj assign to the param {c:1, d:3}
In case when param is defined, I would like to have param data {a:2, b:3}
Use a ternary operator in the function parameter section to determine which properties to log:
const obj = {
/*param: {
a: 2,
b: 3
},*/
c: 1,
d: 3
}
const fun = (args = obj.param ? obj.param : obj) => {
console.log(args)
}
fun(obj)
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' }
Consider a function returns an nested object and I want to modify the property inside the nested object.
In the below example, I'm calling the function many times or I need to store it in a temporary variable. Is there a way to invoke only once inside the braces and spread/modify inside the same object many times.
const getObject = () => {
return {
a: {
b: {
c: 1,
d: 2,
}
},
e: 3
}
}
var modifiedD = {
...getObject(),
a: {
b: {
...getObject().a.b,
d: 4
}
}
}
console.log(modifiedD);
when declaring a key after ...getObject() it replace the whole value. It does not merge the inner object behind a.
So you could do it as you have done and call getObject() multiple time.
An other solution could be to handle it using a function of your own merging the objects, like :
function mergeObjects(obj1, obj2) {
// We are going to copy the value of each obj2 key into obj1
Object.keys(obj2).forEach((x) => {
// If we have an object, we go deeper
if (typeof obj2[x] === 'object') {
if (obj1[x] === void 0) {
obj1[x] = {};
}
mergeObjects(obj1[x], obj2[x]);
} else {
obj1[x] = obj2[x];
}
});
return obj1;
}
const getObject = () => {
return {
a: {
b: {
c: 1,
d: 2,
}
},
e: 3
}
}
const modifiedD = mergeObjects(getObject(), {
a: {
b: {
d: 4,
},
},
});
console.log(modifiedD);
WARNING, the function I have made mutate the object which may not be the best answer
Or call it only once and then set the keys one by one like :
const getObject = () => {
return {
a: {
b: {
c: 1,
d: 2,
}
},
e: 3
}
}
const modifiedD = getObject();
modifiedD.a.b.d = 4;
console.log(modifiedD);
Further to my previous answer, as Grégory NEUT pointed out you could have a lot larger complexity.
If so, you could simply create two objects and then merge them. I found a function code snippet to be able to do that using Object.assign
Example:
const getObject = () => {
return {
a: {
b: {
c: 1,
d: 2,
}
},
e: 3
}
}
var modifiedD = getObject();
var newD = {
a: {
b: {
d: 4
},
y: 1
},
z: 20
}
/** TAKEN FROM https://gist.github.com/ahtcx/0cd94e62691f539160b32ecda18af3d6 **/
// Merge a `source` object to a `target` recursively
const merge = (target, source) => {
// Iterate through `source` properties and if an `Object` set property to merge of `target` and `source` properties
for (let key of Object.keys(source)) {
if (source[key] instanceof Object) Object.assign(source[key], merge(target[key], source[key]))
}
// Join `target` and modified `source`
Object.assign(target || {}, source)
return target
}
modifiedD = merge(modifiedD, newD);
console.log(modifiedD);
You can try the following:
getParentObj(path, obj) {
return path.split('.').reduce((o,i)=>o[i], obj);
}
const parent = getParentObj('a.b', getObject());
parent[d] = 24;
how to compare two objects for equality if they have functions? lodash's isEqual works really well until functions are thrown in:
_.isEqual({
a: 1,
b: 2
}, {
b: 2,
a: 1
});
// -> true
_.isEqual({
a: 1,
b: 2,
c: function () {
return 1;
}
}, {
a: 1,
b: 2,
c: function () {
return 1;
}
});
// -> false
This is what I tried:
_.isEqual(o1, o2, function(val1, val2) {
if(_.isFunction(val1) && _.isFunction(val2)) {
return val1.toString() === val2.toString();
}
})
Lodash supports a customizer function which allows you to write your own equality checks. This seems to be a good enough test to see if the functions are character by character the same.
Are you sure you want to compare functions? If you only care about comparing every property that isn't a function, this is easy to do with lodash:
var o1 = { a: 1, b: 2, c: function() { return 1; } },
o2 = { a: 1, b: 2, c: function() { return 1; } };
_.isEqual(o1, o2)
// → false
_.isEqual(_.omit(o1, _.functions(o1)), _.omit(o2, _.functions(o2)));
// → true
The functions() function returns a list of function properties, and using omit(), you can get rid of them.
Try isEqualWith instead:
import { isEqualWith, isFunction } from 'lodash-es'
const o1 = { fn() {} }
const o2 = { fn() {} }
const equal = isEqualWith(o1, o2, (v1, v2) =>
// if `customizer` returns `undefined`, comparisons are handled by the method instead
isFunction(v1) && isFunction(v2) ? `${v1}` === `${v2}` : undefined,
)
console.log({ equal }) // { equal: true }
As the lodash documentation states:
Functions and DOM nodes are not supported.
https://lodash.com/docs#isEqual