1

I'm trying to delete the object properties that don't evaluate to true. What am I doing wrong?

var object = {
  obj1: NaN,
  obj2: false,
  obj3: "Don't delete",
  obj4: "Please don't delete"

};

var onlyTruthy = function(object) {
  for (var key in object) {
    if (object[key] === false) {
      delete object[key];
    }
  }
  return(object)
};
Aaron
  • 49
  • 1
  • 1
  • 4
  • should properties with `NaN` deleted? – Nina Scholz Jun 23 '16 at 07:31
  • You're using `=== false` that will only check for falsey `boolean`, not for anything that is *evaulated* to be falsey. Try `!object[key]` instead. Also, you better use `Object.keys` instead. – haim770 Jun 23 '16 at 07:34
  • What is your expected result from that function when you pass in the variable named `object`? Please add that info to the question. – Merlyn Morgan-Graham Jun 23 '16 at 07:34
  • None of your example object's properties "evaluate to true". But two of them are "truthy". – nnnnnn Jun 23 '16 at 07:35

4 Answers4

5

For deleting all falsy properties, you could use just a check of the value.

if (!object[key]) {
    delete object[key];
}

With your check object[key] === false, you perform a strict comparison with false. This means, the value is checked against the type (Boolean) and the same value. But you need - kind of - less. Just a check for a not truthy value.

Please keep in mind, that properties with value 0 are deleted too.

Working code:

var object = { obj1: NaN, obj2: false, obj3: "Don't delete", obj4: "Please don't delete" },
    onlyTruthy = function (object) {
        for (var key in object) {
            if (!object[key]) {
                delete object[key];
            }
        }
        return object;
    };

onlyTruthy(object);
console.log(object);
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • adding to that, triple equals is strict equality. So since NaN is not false, NaN === false, will be false – derp Jun 23 '16 at 07:34
0

Just use if(!object[key]) for truth values without comparison with exact falsy values.

Yury
  • 1
0

I'm trying to delete the object properties that don't evaluate to true. What am I doing wrong?

The problem is that you're using the "identity" or "strict equality" operator: === instead of the normal "equality" operator: ==. You aren't allowing the program to do any sort of finagling when you ask it "are these two things the same?".

Here's some examples:

 1   ==  1        // true
"1"  ==  1        // true
 1   == '1'       // true
 0   == false     // true
 0   == null      // false

 0   == undefined // false
null == undefined // true

vs:

3 === 3   // true
3 === '3' // false!

When you write ... === false, the only time that will "evaluate to true" is when the variable is actually equal to false. It won't "evaluate to true" if the variable was null or undefined.

See this question for even more detail on the problem:

Which equals operator (== vs ===) should be used in JavaScript comparisons?

Just changing the === operator to == isn't going to solve things, either. You're going to have to more closely match the problem definition, and check if things don't evaluate to true.

This "evaluates to true" concept is so common in JS that they built it straight into their flow control statements, like if and while:

if (... something that evaluates to true ...) {
   // ... do something
}

while (... something that evaluates to true ...) {
   // ... do something
}

If you combine this with the logical not operator, then you can use this same "evaluates to true" check to find things that don't evaluate to true:

if (!object[key]) {
  delete object[key];
}

This is the "right" way to do things in Javascript (or at least the most "canonical").

Community
  • 1
  • 1
Merlyn Morgan-Graham
  • 58,163
  • 16
  • 128
  • 183
  • The first half of your answer is incorrect, because `== false` doesn't work for the OP's data either (it won't work for falsy values `NaN`, `null`, and `undefined`). – nnnnnn Jun 23 '16 at 08:14
  • @nnnnnn: I see the problem with what you are pointing out. I imply that "fixing the equality operator" would work, though I don't state explicitly that checking for false isn't the same thing as checking that it evaluates to true, and that they'd need to further correct the expression. I think this is because I was intending to point out the `===` part with the first section. I did some tweaks that slightly improve this, though I admit I should unravel the first "solution" suggestion a bit further. – Merlyn Morgan-Graham Jun 23 '16 at 09:09
0

Due to discussions over delete performance, if just want to filter unwanted properties and don't mind to use a new variable this would be a good answer:

var object = { obj1: NaN, obj2: false, obj3: "Don't delete", obj4: "Please don't delete" },
    result = {};
Object.keys(object).forEach(k => object[k] && (result[k] = object[k]));

console.log(result);
Community
  • 1
  • 1
Morteza Tourani
  • 3,506
  • 5
  • 41
  • 48