How to check if variable is null, but allow 1 and 0? - javascript

I use the following code currently
if (oldValue) ...
It works well in case oldValue is null, but in case it is 0, it also returns false, when I expect true. So, how should I check for null value? I was thinking about
if (oldValue!=null) ...
but it doesn't work as I've expected.

To answer your question directly, if your allowed values are 0 and 1 the if statement should look like:
if (0 === oldValue || 1 === oldValue) {
...
}
This is (in my opinion) the clearest way to state which values are allowed.
For a more details explanation see below:
This has to do with truthy and falsy values.
null evaluates to false, as do 0, "", undefined and NaN, these are called falsy values.
Likewise, some values evaluate to true. Such as: "a string", "0" (non empty string "0"), any number other than 0 (including negative numbers), Arrays and Objects (even empty ones). These are truthy values.
There are some unexpected results:
"" == false // true
0 == false // true
but:
NaN == false // false
null == false // false
In practice you should always use the identity operator === instead of equality (==). This ensures that you know what type your variable is expected to be (String, Number, Object) and what the exceptional states are.
Some examples:
If you're getting a value from an input field it will always be a string - the special case is the empty string. Coincidentally this is a falsy value.
If you're counting elements and you need to do something special in case there are no elements - the special case is 0. Coincidentally this is a falsy value.
If you're trying to parse a number from a string using parseInt or parseFloat - the special case NaN (check with isNaN()). Coincidentally this is a falsy value.
If you're checking if a substring occurs within a string using indexOf - the special case is -1 (because 0 is a valid index). This is not a falsy value, but if(str.indexOf(substr)) is most certainly wrong because it is unclear the author knows about the possibly allowed value 0 (which is falsy)
The point here is: the special cases usually are well defined. Harnessing that allows you to always use the identity operator ===. The equality operator == and falsiness is a common source of bugs.
For reference:
"" === false // false
0 === false // false
NaN === false // false
null === false // false
false === false // true (of course)
NaN === NaN // strange, but makes sense
"a" === "a" // yay!

Short answer: If you want to test exactly whether the variable does not have the value null, then change your code to:
if (oldValue !== null) ...
(However, you should think about whether the oldValue might be undefined rather than null, which would have to be a separate case.)
See Frits van Campen's answer for the details of the difference between ==/!= and ===/!==.

Related

Why does an empty filter act as a Boolean? [duplicate]

What are the values in JavaScript that are 'falsey', meaning that they evaluate as false in expressions like if(value), value ? and !value?
There are some discussions of the purpose of falsey values on Stack Overflow already, but no exhaustive complete answer listing what all the falsey values are.
I couldn't find any complete list on MDN JavaScript Reference, and I was surprised to find that the top results when looking for a complete, authoritative list of falsey values in JavaScript were blog articles, some of which had obvious omissions (for example, NaN), and none of which had a format like Stack Overflow's where comments or alternative answers could be added to point out quirks, surprises, omissions, mistakes or caveats. So, it seemed to make sense to make one.
Falsey values in JavaScript
false
Zero of Number type: 0 and also -0, 0.0, and hex form 0x0 (thanks RBT)
Zero of BigInt type: 0n and 0x0n (new in 2020, thanks GetMeARemoteJob)
"", '' and `` - strings of length 0
null
undefined
NaN
document.all (in HTML browsers only)
This is a weird one. document.all is a falsey object, with typeof as undefined. It was a Microsoft-proprietory function in IE before IE11, and was added to the HTML spec as a "willful violation of the JavaScript specification" so that sites written for IE wouldn't break on trying to access, for example, document.all.something; it's falsy because if (document.all) used to be a popular way to detect IE, before conditional comments. See Why is document.all falsy? for details
"Falsey" simply means that JavaScript's internal ToBoolean function returns false. ToBoolean underlies !value, value ? ... : ...; and if (value). Here's its official specification (2020 working draft) (the only changes since the very first ECMAscript specification in 1997 are the addition of ES6's Symbols, which are always truthy, and BigInt, mentioned above:
Argument type
Result
Undefined
Return false.
Null
Return false.
Boolean
Return argument.
Number
If argument is +0, -0, or NaN, return false; otherwise return true.
String
If argument is the empty String (its length is zero), return false; otherwise return true.
BigInt
If argument is 0n, return false; otherwise return true.
Symbol
Return true.
Object
Return true.
Comparisons with == (loose equality)
It's worth talking about falsy values' loose comparisons with ==, which uses ToNumber() and can cause some confusion due to the underlying differences. They effectively form three groups:
false, 0, -0, "", '' all match each other with ==
e.g. false == "", '' == 0 and therefore 4/2 - 2 == 'some string'.slice(11);
null, undefined match with ==
e.g. null == undefined but undefined != false
It's also worth mentioning that while typeof null returns 'object', null is not an object, this is a longstanding bug/quirk that was not fixed in order to maintain compatibility. It's not a true object, and objects are truthy (except for that "wilful violation" document.all when Javascript is implemented in HTML)
NaN doesn't match anything, with == or ===, not even itself
e.g. NaN != NaN, NaN !== NaN, NaN != false, NaN != null
With "strict equality" (===), there are no such groupings. Only false === false.
This is one of the reasons why many developers and many style guides (e.g. standardjs) prefer === and almost never use ==.
Truthy values that actually == false
"Truthy" simply means that JavaScript's internal ToBoolean function returns true. A quirk of Javascript to be aware of (and another good reason to prefer === over ==): it is possible for a value to be truthy (ToBoolean returns true), but also == false.
You might think if (value && value == false) alert('Huh?') is a logical impossibility that couldn't happen, but it will, for:
"0" and '0' - they're non-empty strings, which are truthy, but Javascript's == matches numbers with equivalent strings (e.g. 42 == "42"). Since 0 == false, if "0" == 0, "0" == false.
new Number(0) and new Boolean(false) - they're objects, which are truthy, but == sees their values, which == false.
0 .toExponential(); - an object with a numerical value equivalent to 0
Any similar constructions that give you a false-equaling value wrapped in a type that is truthy
[], [[]] and [0] (thanks cloudfeet for the JavaScript Equality Table link)
Some more truthy values
These are just a few values that some people might expect to be falsey, but are actually truthy.
-1 and all non-zero negative numbers
' ', " ", "false", 'null'... all non-empty strings, including strings that are just whitespace
Anything from typeof, which always returns a non-empty string, for example:
typeof null (returns a string 'object' due to a longstanding bug/quirk)
typeof undefined (returns a string 'undefined')
Any object (except that "wilful violation" document.all in browsers). Remember that null isn't really an object, despite typeof suggesting otherwise. Examples:
{}
[]
function(){} or () => {} (any function, including empty functions)
Error and any instance of Error
Any regular expression
Anything created with new (including new Number(0) and new Boolean(false))
Any Symbol
true, 1, "1" and [1] return true when compared to each other with ==.
Don't forget about the non-empty string "false" which evaluates to true
Just to add to #user568458's list of falsy values:
In addition to integer number 0, the decimal number 0.0, 0.00 or any such zeroish number is also a falsy value.
var myNum = 0.0;
if(myNum){
console.log('I am a truthy value');
}
else {
console.log('I am a falsy value');
}
Above code snippet prints I am a falsy value
Similarly hex representation of the number 0 is also a falsy value as shown in below code snippet:
var myNum = 0x0; //hex representation of 0
if(myNum){
console.log('I am a truthy value');
}
else {
console.log('I am a falsy value');
}
Above code snippet again prints I am a falsy value.
Addition to the topic, as of ES2020 we have a new value which is falsy, it's BigInt zero (0n):
0n == false // true
-0n == false // true
0n === false // false
-0n === false // false
So with this, we now have 7 "falsy" values in total (not including document.all as mentioned by user above since it's part of DOM and not JS).

trouble with truthy/falsey

A quick intro, I am a total noob learning JS and feel that it's going well, however I am doing a simple exercise right now and I'm hung up on something.
I have learned that:
a falsey value is a value that is considered false when encountered in a boolean context
ex: false, 0, -0, 0n, "", null, undefined, NaN (Not a number)
truthy is everything other than falsey (such as a String, boolean true, any number not 0 etc.)
so in my example below, if anyone could help me understand why value => value == true, would print out false (as was the case) when I have a string value in my array ("Angela"). Thanks!
let values = [11, NaN, [], "Angela"]
function checkForFalsey() {
if (values.some(value => value == true)) {
console.log("At least one item is falsey")
}
}
checkForFalsey()
A string is neither truthy nor falsy. What's happening is called type coercion. Since string and Boolean are not the same type, JavaScript coerces one of the types to match the other then checks equality (a high level explanation). See here for a detailed explanation: https://javascriptweblog.wordpress.com/2011/02/07/truth-equality-and-javascript/
So when you do "abc" == true JavaScript is coercing both values to a number type. A string is not a number, so toNumber("abc") returns NaN. It also coerces true to a number, which returns 1 in this case (1 is true, 0 is false, as you mentioned).
For what it's worth, NaN is also not truthy or falsy. Comparing it to true or false will always result in false.
Edit:
The question was a bit confusing because of the snippet, I understood that you were trying to look for falsy values.
The reason why:
value => value == true
would print out false it's because none of the elements of the array is equal to true.
You are correct about what a falsy value is, but that doesn't mean that a truthy value would be == to true.
Here you can read more about it:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness
One way of checking for truthy values would be:
(values.some(value => value != false))
or
(values.some(value => !!value === true))
Old answer:
Because the method you use tests that at least one element in the array matches the condition.
You can read more here
If you want to check that all elements of the array matches the condition, then you can use .every()
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every
let values = [11, NaN, [], ""]
function checkForFalsey() {
if (values.every(value => value == false)) {
console.log("All values are falsey");
} else {
console.log("NOT all values are falsey");
}
}
checkForFalsey()

Equality of truthy and falsy values (JavaScript)

I've encountered something which seems inconsistent on the part of the interpreter, though I know it probably makes sense and I just don't understand it. It has to do with evaluating the equality of a truthy/falsy values and Booleans.
Example 1:
if (document.getElementById('header')) {
//run code here
}
If the element with an id of 'header' is found in the document, the condition is true because the presence of an object is considered truthy.
Example 2:
if (document.getElementById('header) == true) {
// run code here
}
Presuppose the referenced element is found within the document. It was explained to me that this condition will evaluate to false because a truthy value does not equal a Boolean value of true.
This doesn't seem to make sense. The presence of the object is considered truthy due to type coercion, so therefore it should equal true even though the data types are different.
Consider the following:
(false == 0) // evaluates to true
(false === 0) // evaluates to false
This is a case where false equals 0 is true when you use the equals to operator. Because 0 is considered a falsy value, it is equal to the Boolean value of false. The values are the same and the data types are different.
To me, (document.getElementById('header') == true) and (false == 0) are the same thing. And yet, they both evaluate to something different.
Can someone please explain to me why this is the case? I've been reading different descriptions of this, but no one seems to explain it in-depth.
document.getElementById('header') returns a DOM object or null. So, in your second comparison (assuming it is resolving to an object), you're comparing:
if (obj == true)
A DOM object is not == to true.
To see why, you have to go to the ECMAScript rules for automatic type conversion which you can see in the ECMAScript 5 specification here: http://www.ecma-international.org/ecma-262/5.1/#sec-11.9.3.
The operative rules when comparing an object == boolean are all the way down to rules 9 and 10.
If Type(x) is Object and Type(y) is either String or Number, return the result of the comparison ToPrimitive(x) == y.
Return false.
Rule 9 is the first rule where Type(x) is Object and the two types are not the same, so it's the first one to check.
Since Type(y) is Boolean, it does not pass rule 9.
Thus, when it hasn't passed any rules 1-9, it evaluates to false.
When you do this comparison:
(false == 0) // evaluates to true
you're looking at rule #6 in the type conversion rules which will do:
ToNumber(false) == 0
which will resolve to:
0 == 0
which will be true.
For this one:
(false === 0)
Whenever you use ===, if the two types are different, then the result is immediately false so this evaluates to false. === requires type AND value to be the same so if the type is not the same, then it doesn't even attempt to compare the value. No type conversion is ever done with === which is one of the useful reasons to use it.
You should understand that the truthy and falsey rules apply to only a single check like this with no == or === in the comparison:
if (obj)
They do not apply when you are comparing x == y. For that, you have to refer to the type conversion rules in section 11.9.3 of the specification (linked above).
Presuppose the referenced element is found within the document. It was explained to me that this condition will evaluate to false because a truthy value does not equal a Boolean value of true.
You're right, it doesn't make sense because whoever explained that to you is wrong.
The presence of a DOM element will evaluate to true and if it doesn't exist, it will evaluate to false (with a double-equals vs. triple). If in the event they are using triple equals, you can simply try:
!!document.getElementById('someNodeId') and it will return a boolean value.
You can always try this in the console if you want to be sure.
!!document.getElementById('notify-container');
>> true
!!document.getElementById('non-existing-node-goes-here');
>> false
Edit: I didn't read the example clearly or the example was updated. Yeah, you're using double equal. The element is truthy, but it's not "true".
When the if() statement is executing, it's checking if there is a truthy value inside the parenthesis. The == operator is checking whether the two values are equal in nature. In JavaScript, true and false are == to 1 and 0, respectively; hence why you can type (4 + true) and get 5, or false*6 and get 0!
When you type something == true, you're really checking if something == 1.
If something isn't a boolean value it's not going to be the same as 1.
Perhaps an explanation of your postulate "The presence of the object is considered truthy due to type coercion, so therefore it should equal true."
If any truthy value is equal to true,
then any truthy value is equal to any truthy value (by transitive property, a=b,c=b, therefore a=c),
however, this would not hold true for all cases! ("blue" == "green", 5 == "six" simply because they are each non-false values. This would make the == fairly worthless!)
The conclusion does not follow, so therefore the postulate is invalid. In general, you should use === if you need to check if two things are truly the same thing.
Hopefully this clears things up!

All falsey values in JavaScript

What are the values in JavaScript that are 'falsey', meaning that they evaluate as false in expressions like if(value), value ? and !value?
There are some discussions of the purpose of falsey values on Stack Overflow already, but no exhaustive complete answer listing what all the falsey values are.
I couldn't find any complete list on MDN JavaScript Reference, and I was surprised to find that the top results when looking for a complete, authoritative list of falsey values in JavaScript were blog articles, some of which had obvious omissions (for example, NaN), and none of which had a format like Stack Overflow's where comments or alternative answers could be added to point out quirks, surprises, omissions, mistakes or caveats. So, it seemed to make sense to make one.
Falsey values in JavaScript
false
Zero of Number type: 0 and also -0, 0.0, and hex form 0x0 (thanks RBT)
Zero of BigInt type: 0n and 0x0n (new in 2020, thanks GetMeARemoteJob)
"", '' and `` - strings of length 0
null
undefined
NaN
document.all (in HTML browsers only)
This is a weird one. document.all is a falsey object, with typeof as undefined. It was a Microsoft-proprietory function in IE before IE11, and was added to the HTML spec as a "willful violation of the JavaScript specification" so that sites written for IE wouldn't break on trying to access, for example, document.all.something; it's falsy because if (document.all) used to be a popular way to detect IE, before conditional comments. See Why is document.all falsy? for details
"Falsey" simply means that JavaScript's internal ToBoolean function returns false. ToBoolean underlies !value, value ? ... : ...; and if (value). Here's its official specification (2020 working draft) (the only changes since the very first ECMAscript specification in 1997 are the addition of ES6's Symbols, which are always truthy, and BigInt, mentioned above:
Argument type
Result
Undefined
Return false.
Null
Return false.
Boolean
Return argument.
Number
If argument is +0, -0, or NaN, return false; otherwise return true.
String
If argument is the empty String (its length is zero), return false; otherwise return true.
BigInt
If argument is 0n, return false; otherwise return true.
Symbol
Return true.
Object
Return true.
Comparisons with == (loose equality)
It's worth talking about falsy values' loose comparisons with ==, which uses ToNumber() and can cause some confusion due to the underlying differences. They effectively form three groups:
false, 0, -0, "", '' all match each other with ==
e.g. false == "", '' == 0 and therefore 4/2 - 2 == 'some string'.slice(11);
null, undefined match with ==
e.g. null == undefined but undefined != false
It's also worth mentioning that while typeof null returns 'object', null is not an object, this is a longstanding bug/quirk that was not fixed in order to maintain compatibility. It's not a true object, and objects are truthy (except for that "wilful violation" document.all when Javascript is implemented in HTML)
NaN doesn't match anything, with == or ===, not even itself
e.g. NaN != NaN, NaN !== NaN, NaN != false, NaN != null
With "strict equality" (===), there are no such groupings. Only false === false.
This is one of the reasons why many developers and many style guides (e.g. standardjs) prefer === and almost never use ==.
Truthy values that actually == false
"Truthy" simply means that JavaScript's internal ToBoolean function returns true. A quirk of Javascript to be aware of (and another good reason to prefer === over ==): it is possible for a value to be truthy (ToBoolean returns true), but also == false.
You might think if (value && value == false) alert('Huh?') is a logical impossibility that couldn't happen, but it will, for:
"0" and '0' - they're non-empty strings, which are truthy, but Javascript's == matches numbers with equivalent strings (e.g. 42 == "42"). Since 0 == false, if "0" == 0, "0" == false.
new Number(0) and new Boolean(false) - they're objects, which are truthy, but == sees their values, which == false.
0 .toExponential(); - an object with a numerical value equivalent to 0
Any similar constructions that give you a false-equaling value wrapped in a type that is truthy
[], [[]] and [0] (thanks cloudfeet for the JavaScript Equality Table link)
Some more truthy values
These are just a few values that some people might expect to be falsey, but are actually truthy.
-1 and all non-zero negative numbers
' ', " ", "false", 'null'... all non-empty strings, including strings that are just whitespace
Anything from typeof, which always returns a non-empty string, for example:
typeof null (returns a string 'object' due to a longstanding bug/quirk)
typeof undefined (returns a string 'undefined')
Any object (except that "wilful violation" document.all in browsers). Remember that null isn't really an object, despite typeof suggesting otherwise. Examples:
{}
[]
function(){} or () => {} (any function, including empty functions)
Error and any instance of Error
Any regular expression
Anything created with new (including new Number(0) and new Boolean(false))
Any Symbol
true, 1, "1" and [1] return true when compared to each other with ==.
Don't forget about the non-empty string "false" which evaluates to true
Just to add to #user568458's list of falsy values:
In addition to integer number 0, the decimal number 0.0, 0.00 or any such zeroish number is also a falsy value.
var myNum = 0.0;
if(myNum){
console.log('I am a truthy value');
}
else {
console.log('I am a falsy value');
}
Above code snippet prints I am a falsy value
Similarly hex representation of the number 0 is also a falsy value as shown in below code snippet:
var myNum = 0x0; //hex representation of 0
if(myNum){
console.log('I am a truthy value');
}
else {
console.log('I am a falsy value');
}
Above code snippet again prints I am a falsy value.
Addition to the topic, as of ES2020 we have a new value which is falsy, it's BigInt zero (0n):
0n == false // true
-0n == false // true
0n === false // false
-0n === false // false
So with this, we now have 7 "falsy" values in total (not including document.all as mentioned by user above since it's part of DOM and not JS).

Is true == 1 and false == 0 in JavaScript?

I was reading a good book on JavaScript.
It started with:
Boolean type take only two literal values: true and false. These are distinct from numeric values, so true is not equal to 1, and false is not equal to 0.
However, I observed following:
if(1==true)
document.write("oh!!! that's true"); //**this is displayed**
I know, that every type in JavaScript has a Boolean equivalent.
But then, what's the truth?
It's true that true and false don't represent any numerical values in Javascript.
In some languages (e.g. C, VB), the boolean values are defined as actual numerical values, so they are just different names for 1 and 0 (or -1 and 0).
In some other languages (e.g. Pascal, C#), there is a distinct boolean type that is not numerical. It's possible to convert between boolean values and numerical values, but it doesn't happen automatically.
Javascript falls in the category that has a distinct boolean type, but on the other hand Javascript is quite keen to convert values between different data types.
For example, eventhough a number is not a boolean, you can use a numeric value where a boolean value is expected. Using if (1) {...} works just as well as if (true) {...}.
When comparing values, like in your example, there is a difference between the == operator and the === operator. The == equality operator happily converts between types to find a match, so 1 == true evaluates to true because true is converted to 1. The === type equality operator doesn't do type conversions, so 1 === true evaluates to false because the values are of different types.
In JavaScript, == is pronounced "Probably Equals".
What I mean by that is that JavaScript will automatically convert the Boolean into an integer and then attempt to compare the two sides.
For real equality, use the === operator.
Try the strict equality comparison:
if(1 === true)
document.write("oh!!! that's true"); //**this is not displayed**
The == operator does conversion from one type to another, the === operator doesn't.
From the ECMAScript specification, Section 11.9.3 The Abstract Equality Comparison Algorithm:
The comparison x == y, where x and y are values, produces true or
false. Such a comparison is performed as follows:
If Type(y) is Boolean, return the result of the comparison x == ToNumber(y).
Thus, in, if (1 == true), true gets coerced to a Number, i.e. Number(true), which results in the value of 1, yielding the final if (1 == 1) which is true.
if (0 == false) is the exact same logic, since Number(false) == 0.
This doesn't happen when you use the strict equals operator === instead:
11.9.6 The Strict Equality Comparison Algorithm
The comparison x === y, where x and y are values, produces true or
false. Such a comparison is performed as follows:
If Type(x) is different from Type(y), return false.
Ah, the dreaded loose comparison operator strikes again. Never use it. Always use strict comparison, === or !== instead.
Bonus fact: 0 == ''
When compare something with Boolean it works like following
Step 1: Convert boolean to Number Number(true) // 1 and Number(false) // 0
Step 2: Compare both sides
boolean == someting
-> Number(boolean) === someting
If compare 1 and 2 with true you will get the following results
true == 1
-> Number(true) === 1
-> 1 === 1
-> true
And
true == 2
-> Number(true) === 1
-> 1 === 2
-> false
Actually every object in javascript resolves to true if it has "a real value" as W3Cschools puts it. That means everything except "", NaN, undefined, null or 0.
Testing a number against a boolean with the == operator indeed is a tad weird, since the boolean gets converted into numerical 1 before comparing, which defies a little bit the logic behind the definition.
This gets even more confusing when you do something like this:
var fred = !!3; // will set fred to true
var joe = !!0; // will set joe to false
alert("fred = "+ fred + ", joe = "+ joe);
not everything in javascript makes a lot of sense ;)
Use === to equate the variables instead of ==.
== checks if the value of the variables is similar
=== checks if the value of the variables and the type of the variables are similar
Notice how
if(0===false) {
document.write("oh!!! that's true");
}​
and
if(0==false) {
document.write("oh!!! that's true");
}​
give different results
In a way, yes it is 1.
Try these examples in Chrome console:
> 2==true
false
> 1==true
true
> true + 1
2
> true + 2
3
> true + true
2
So, the answer is:
yes, as soon as you use true in any arithmetical context, it's treated as numeric 1, or as Bruce Lee would say, it becomes one. The same way, false is practically zero. But also,
no, if you ask Javascript what it thinks of true, it will say it's a boolean:
> typeof true
'boolean'
It's no surprise in a loosely typed language that sometimes things are not what they are but how you look at them. And if you add true to a string, it will not add 1 but "true" as a string, so at the end of the day, it's by no means equivalent to one. Let me end this with a horrible pun:
true is not a number - but it looks like one
with == you are essentially comparing whether a variable is falsey when comparing to false or truthey when comparing to true. If you use ===, it will compare the exact value of the variables so true will not === 1

Categories

Resources