Why Does If("String") Evaluate "String" as True But If ("String"==True) Does Not

why does if(string) evaluate string as true but if (string==true) does not?

It is being cast to Boolean. Any non-empty string evaluates to true.

From the ECMAScript Language Specification:

12.5 The if statement


Semantics


The production IfStatement: if ( Expression ) Statement else Statement is evaluated as follows:

  1. Let exprRef be the result of evaluating Expression.
  2. If ToBoolean(GetValue(exprRef)) is true, then
    • Return the result of evaluating the first Statement.
  3. Else,
    • Return the result of evaluating the second Statement.

9.2 ToBoolean


The abstract operation ToBoolean converts its argument to a value of type Boolean according to Table 11:

Table 11 - ToBoolean Conversions


Undefined: false
Null: false
Boolean: The result equals the input argument (no conversion).

Number: The result is false if the argument is +0, -0, or NaN; otherwise the result is true.

String: The result is false if the argument is the empty String (its length is zero);
otherwise the result is true.

Object: true


As far as the == operator is concerned, it's complicated, but the gist of it is that if you compare a number to a non-number the latter is converted into a number. If you compare a boolean against a non-boolean, the boolean is first converted to a number, and then the previous sentence applies.

See section 11.9.3 for details.

// Call this x == y.
if ("string" == true)

// Rule 6: If Type(y) is Boolean,
// return the result of the comparison x == ToNumber(y).
if ("string" == Number(true))

// Rule 5: If Type(x) is String and Type(y) is Number,
// return the result of the comparison ToNumber(x) == y.
if (Number("string") == Number(true))

// The above is equivalent to:
if (NaN == 1)

// And NaN compared to *anything* is false, so the end result is:
if (false)

Why does true == true show false in JavaScript?

Because "true" is converted to NaN, while true is converted to 1. So they differ.

Like you reported, both are converted to numbers, because at least true can be (see Erik Reppen's comment), and then compared.

Why does Python evaluate strings/numbers as True in if statements yet myNumber == True returns False?

You're testing different things here.

The if just checks if the bool of the expression (see also "Truth value testing") is True not if the identity is equal to True.

So what is actually tested by the if is:

>>> bool(5) == True
True

In JavaScript, why is 0 equal to false, but when tested by 'if' it is not false by itself?

The reason is because when you explicitly do "0" == false, both sides are being converted to numbers, and then the comparison is performed.

When you do: if ("0") console.log("ha"), the string value is being tested. Any non-empty string is true, while an empty string is false.

Equal (==)

If the two operands are not of the same type, JavaScript converts the operands then applies strict comparison. If either operand is a number or a boolean, the operands are converted to numbers if possible; else if either operand is a string, the other operand is converted to a string if possible. If both operands are objects, then JavaScript compares internal references which are equal when operands refer to the same object in memory.

(From Comparison Operators in Mozilla Developer Network)

Why does this evaluate as false?

When you use the new keyword you are creating an object. If you were to check the typeof new String('hello') you will see that it is of type object. Checking the type of 'hello' on its own will yield string.

As you may know, using a strict equals operator (===) will check for both value and type, so it will return false due to the types not matching.

The reason the expression without the new keyword returns true is because calling upon the String global object is not the same as calling the constructor using new:

String literals (denoted by double or single quotes) and strings returned from String calls in a non-constructor context (i.e., without using the new keyword) are primitive strings.

As such, the type of the return value will be string and not object, so the strict check will return true.

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

The strict equality operator (===) behaves identically to the abstract equality operator (==) except no type conversion is done, and the types must be the same to be considered equal.

Reference: Javascript Tutorial: Comparison Operators

The == operator will compare for equality after doing any necessary type conversions. The === operator will not do the conversion, so if two values are not the same type === will simply return false. Both are equally quick.

To quote Douglas Crockford's excellent JavaScript: The Good Parts,

JavaScript has two sets of equality operators: === and !==, and their evil twins == and !=. The good ones work the way you would expect. If the two operands are of the same type and have the same value, then === produces true and !== produces false. The evil twins do the right thing when the operands are of the same type, but if they are of different types, they attempt to coerce the values. the rules by which they do that are complicated and unmemorable. These are some of the interesting cases:

'' == '0'           // false
0 == '' // true
0 == '0' // true

false == 'false' // false
false == '0' // true

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

' \t\r\n ' == 0 // true

Equality Comparison Table

The lack of transitivity is alarming. My advice is to never use the evil twins. Instead, always use === and !==. All of the comparisons just shown produce false with the === operator.


Update:

A good point was brought up by @Casebash in the comments and in @Phillipe Laybaert's answer concerning objects. For objects, == and === act consistently with one another (except in a special case).

var a = [1,2,3];
var b = [1,2,3];

var c = { x: 1, y: 2 };
var d = { x: 1, y: 2 };

var e = "text";
var f = "te" + "xt";

a == b // false
a === b // false

c == d // false
c === d // false

e == f // true
e === f // true

The special case is when you compare a primitive with an object that evaluates to the same primitive, due to its toString or valueOf method. For example, consider the comparison of a string primitive with a string object created using the String constructor.

"abc" == new String("abc")    // true
"abc" === new String("abc") // false

Here the == operator is checking the values of the two objects and returning true, but the === is seeing that they're not the same type and returning false. Which one is correct? That really depends on what you're trying to compare. My advice is to bypass the question entirely and just don't use the String constructor to create string objects from string literals.

Reference
http://www.ecma-international.org/ecma-262/5.1/#sec-11.9.3

Why do both [] == true and ![] == true evaluate to false?

It's the way coercion works.

The first step of coercion is to convert any non primitive types to primitive types, then using a set of rules convert the left, right or both sides to the same type. You can find these rules here.

In your case [] == true, would pass through these 4 steps:

  1. [] == true
  2. [] == 1
  3. "" == 1
  4. 0 == 1

Whereas based on operator precedence the ! in ![] == true is executed first so the expression is converted to false == true which is obviously false.

You can try the live demo by Felix Kling to better understand how the sameness operator works.

In more words:

The value ![] is false, because [] is an Object (arrays are objects) and all objects, not including null, are truthy. So any array, even if it is empty will always be a truthy, and the opposite of a truthy is always false. The easiest way to check if a value is a truthy is by using !!.

console.log("![]: " + ![]);
console.log("!![]: " + !![]);

Why does my boolean not evaluate correctly?

The problem is your historyEntry = value.value;, in this case value.value is a string, not a bool.

You can do historyEntry = (value.value == 'true');

Demo

var unindexed_frmVersionCtrl = [{
"name": 'versionControlBool',
value: 'true'
}, {
"name": 'versionCount',
value: '25'
}, {
"name": 'versionControl',
value: 0
}]

var historyEntry = false;

for (const [key, value] of Object.entries(unindexed_frmVersionCtrl)) {
if (value.name == "versionControlBool") {
historyEntry = (value.value == 'true');
console.log("typeof value.value = " + typeof(value.value))
console.log(historyEntry);
}

if (value.name == "versionControl") {
console.log(historyEntry);
if (historyEntry == true) {
value.value = 1;
console.log("lel");
} else {
console.log("false");
value.value = 0;
}
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Why does !!1==1 equal true and !!2==2 equal false?

As per the Operator precedence rules, logical ! has higher priority over ==. So, in both the cases, !! is evaluated first.

Note: Truthiness of various objects have been explained in this answer of mine.

First Case

!!1 == "1"

!1 will be evaluated to false, since 1 is considered Truthy. Negating again we get true. So the expression becomes

true == "1"

Now, the coercion rules kick in as you have used == operator, which evaluates as per the The Abstract Equality Comparison Algorithm defined in ECMAScript 5.1 Specification,

6. If Type(x) is Boolean, return the result of the comparison ToNumber(x) == y.

So, true will be converted to a number, which is 1 as per ToNumber algorithm for Boolean values. Now the expression becomes

1 == "1"

Now,

4. If Type(x) is Number and Type(y) is String,
return the result of the comparison x == ToNumber(y).

So, "1" will be converted to a number and that will give 1, as per the ToNumber algorithm. That is why it shows true in the first case.

Second Case

The same rules are applied here.

!!2 == "2"

becomes

true == "2"

then

1 == "2"

which becomes

1 == 2

which is not true, that is why the second case prints false.



Related Topics



Leave a reply



Submit