I came across a list of data operations and lost value of [0].
I could not find out why. it's good if I change value to [1], but if i put value [0], then it's gone.
Here is the code:
let data = {
title:"hello world",
value: [0]
}
let sanitized = removeNull(data);
console.log(sanitized)
// ------------------------------------------------------------------------
function removeNull(obj) {
Object.keys(obj).forEach(k =>
(obj[k] && typeof obj[k] === 'object') && removeNull(obj[k]) ||
(typeof obj[k] !== 'boolean' && !obj[k] && obj[k] !== undefined) && delete obj[k]
);
return obj;
};
CodePudding user response:
When obj[k]
is 0
, delete obj[k]
is being executed because in the expression:
(obj[k] && typeof obj[k] === 'object') && removeNull(obj[k]) ||
(typeof obj[k] !== 'boolean' && !obj[k] && obj[k] !== undefined) && delete obj[k]
...obj[k]
is falsey (so the entire top line above is false. Then we proceed to check the second line because of the ||.
typeof 0
isNumber
which is!== boolean
, so that's true...!0
is truthy...0 !== undefined
is also true...
which leaves us to check the truthiness of the final term which is delete obj[k]
. ...which happens to be true
by the way, not that it matters, because 0
gets deleted by virtue of us even checking that last term's value.
CodePudding user response:
Some key concepts:
0
is falseytypeof null === 'object'
is truetypeof [] === 'object'
is true
Currently, the code executes as follows:
- When you get to the part of the loop where
obj[k]
=[0]
, removeNull() gets called on[0]
because arrays are of typeobject
. - When we iterate over
[0]
in that call of removeNull(),k
starts as0
(the index in the array), andobj[k]
becomes0
(the value).0
passestypeof 0 !== 'boolean' && !0 && 0 !== undefined
, so it getsdeleted
and turned into an empty item in the array.delete
empties out array elements but doesn't remove the index.
There might be some ways to reorganize the code to make it a little safer and easier to debug, depending on whether you want to remove null in arrays, too.
let data = {
title:"hello world", // not removed
value: [
0, // not removed
null // removed
],
name: null, // removed
author: {
name: null, // removed
hats: false, // not removed
pets: [null] // --> []
partners: [] // --> []
}
}
const sanitized = removeNull(data);
console.log(sanitized)
// -----------------------------------------------------------------------
function removeNull(obj) {
Object.keys(obj).forEach((key) => {
if(obj[key] === null) {
// removes the element differently
// depending on whether obj is array or object.
return Array.isArray(obj) ? obj.splice(key, 1) : delete obj[key]
}
if(typeof obj[key] === 'object') removeNull(obj[key])
})
return obj
}
If you don't care about checking for null
in arrays, add && !Array.isArray(obj)
to the second check, and remove the ternary that decides how to delete.
One note: in addition to returning the new null-less object, this code (and your code) currently also modify the original object.
CodePudding user response:
Update
Ahhh,typeof obj[k] !== 'boolean' && !obj[k] && obj[k] !== undefined
evaluates to true because 0
is considered falsy in Javascript. So !obj[k]
is true.
Original answer
The current removeEmpty function is testing if the result of JSON.stringify(o[k] === "[0]")
is truthy. You probably meant to test if the stringified contents of o[k] are equal to "[0]". So something like JSON.stringify(o[k]) === "[0]"
should solve your problem.