Why do === and == not execute as expected?

Why do === and == not execute as expected?
0

#1

The goal of the ‘Everything Be True’ intermediate algorithm is to check if the predicate (second argument) is truthy on all elements of a collection (first argument). Each of the listed 3 function calls should return TRUE. I solved the algorithm in this manner:

function truthCheck2(collection, pre) {
  return collection.every(function(element) {
    return element[pre];
  });
}
console.log("(element[pre])");
console.log("True: "+ truthCheck2([{"user": "Tinky-Winky", "sex": "male"}, {"user": "Dipsy", "sex": "male"}, {"user": "Laa-Laa", "sex": "female"}, {"user": "Po", "sex": "female"}], "sex"));
console.log("True: "+ truthCheck2([{"name": "Pete", "onBoat": true}, {"name": "Repeat", "onBoat": true, "alias": "Repete"}, {"name": "FastFoward", "onBoat": true}], "onBoat"));
console.log("True: "+ truthCheck2([{"single": "yes"}], "single"));

All three tests return TRUE as expected. However, when I tried to determine if the predicate was truthy using either === or == the first and the third function calls failed. Any idea why using == or === fail to find the truthy?

function truthCheck1(collection, pre) {
  return collection.every(function(element) {
    return element[pre] === true || element[pre] == true;
  });
}
console.log("(element[pre] === true || element[pre] == true)");
console.log("True: "+ truthCheck1([{"user": "Tinky-Winky", "sex": "male"}, {"user": "Dipsy", "sex": "male"}, {"user": "Laa-Laa", "sex": "female"}, {"user": "Po", "sex": "female"}], "sex"));
console.log("True: "+ truthCheck1([{"name": "Pete", "onBoat": true}, {"name": "Repeat", "onBoat": true, "alias": "Repete"}, {"name": "FastFoward", "onBoat": true}], "onBoat"));
console.log("True: "+ truthCheck1([{"single": "yes"}], "single"));


Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36


#2

element[pre] === true is false because element[pre] and true have different types (string and boolean).

element[pre] == true is trickier because of coercion. IIRC, if you compare a string with a boolean using ==, both are coerced to a number. Coercing true to a number gives you 1, so the only way for the comparison to be true is for the string to coerce to 1 as well (if the string is '1').

The best way to determine truthiness is by coercing the value to a boolean:

  • Boolean(element[pre])
  • !!element[pre]
  • If a function is expected to return a true/false value, just return the value itself, like in .every()

Using === to compare with true or false is straightforward, but using == is very, very confusing.

Here’s a handy table from YDKJS:


#3

@kevcomedia, thanks for the detailed response. My takeaway from this experience is to never again attempt to determine truthiness by comparing against True or False. It’s so counter-intuitive how element[pre] gets coerced into a truthy because element[pre] exists and does not equal ‘0’ however a truthy == True comparison is False.