Hi, is there any reason why developers write obj.sth && obj.sth.sth ? Like, checking for the existence of an object key/method before chaining on. After all, both will get evaluated - I think. But turns out that it seems if obj.sth is falsy obj.sth.sth does not get evaluated.
I have been seeing it for a while and ignoring it. I am ready to understand now.
Here is what I ran into:
if (ref.current.contains(e.target)) return; // ref.current was null... understandably, it throws an error
if (ref.current?.contains(e.target)) return; // I have been using optional chaining
if (ref.current && ref.current.contains(e.target) return; // baffles me why it throw no error
This is actually pretty important in “real” programs. In JavaScript, we are not guaranteed that the parameter that is passed into a function will match our expectations, so we have to perform input validation.
Let’s say want to greet your cat and I have:
sayHi(person.cat.name);
But, when person is ArielLeslie, you will have a problem, because I do not have a cat. This will cause an error cannot read "name" of undefined. Syntax errors are bad news and can cause your program to stop running.
We could also have a problem if person is Holly Golightly, because
He’s all right! Aren’t you, Cat? Poor Cat! Poor slob! Poor slob without a name! The way I see it I haven’t got the right to give him one. We don’t belong to each other. We just took up one day by the river.
Depending on what sayHi does, we could get a similar ____ does not exist on undefined error, or we could just end up with a logical error where we do something like print “Hello undefined. You are a handsome cat.”
So what’s the solution? Only perform the action if the data is valid
if (person && person.cat && person.cat.name) {
sayHi(person.cat.name);
}
(This has recently gotten much tidier with optional chaining)
There is something called “short circuiting” in logical operators. It will stop performing checks once they become irrelevant. In the case of &&, it will be false if either of the pieces are falsy, so it stops as soon as it encounters a falsy value (like ref.current).
On the flip side, || conditions will be true if either is truthy, so it stops when it encounters a truthy value.
(This is also why it’s important to get the order correct when doing person && person.cat && person.cat.name. It will stop when it hits an undefined).
In JavaScript every variable has an inherent boolean value, generally known as either truthy or falsy. So if you pass just a variable to if statment, it just checks for its “truthy-ness”.
The following values are always falsy :
false
0 (zero)
'' or "" (empty string)
null
undefined
NaN
Everything else is truthy.
So in the code you posted, in the last line javascript just checks if (ref.current) is a truthy, if it is then after && you can use the variable normally. Because you now know its not a null, undefined or any other falsy value mentioned above.