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 0isNumberwhich is!== boolean, so that's true...!0is truthy...0 !== undefinedis 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:
0is 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(),kstarts as0(the index in the array), andobj[k]becomes0(the value).0passestypeof 0 !== 'boolean' && !0 && 0 !== undefined, so it getsdeletedand turned into an empty item in the array.deleteempties 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.
