JavaScript short circuit evaluation error? - javascript

The two below snippets of JS code have had me confused, in my eyes both should work the same, due to short circuit evaluation. But for some reason snippet '1' causes the error (on the third line):
Cannot read property 'match' of undefined
Array 'a' holds 3 character values user entered into inputs. I want the code to return true if the char is undefined, an empty string, or a letter or number.
To be clear, this fails when a = ['a', '/'];
Snippet 1)
return typeof a[0] === 'undefined' || a[0] === '' || a[0].match(/^[a-z0-9]+$/i)
&& typeof a[1] === 'undefined' || a[1] === '' || a[1].match(/^[a-z0-9]+$/i)
&& typeof a[2] === 'undefined' || a[2] === '' || a[2].match(/^[a-z0-9]+$/i);
Snippet 2)
if (typeof a[0] === 'undefined' || a[0] === '' || a[0].match(/^[a-z0-9]+$/i)) {
if (typeof a[1] === 'undefined' || a[1] === '' || a[1].match(/^[a-z0-9]+$/i)) {
if (typeof a[2] === 'undefined' || a[2] === '' || a[2].match(/^[a-z0-9]+$/i)) {
return true;
}
return false;
}
return false;
}
return false;
Surely a[2].match should never be evaluated if a[2] is undefined due to the first conditional in the 'if'?

The answer is simple. Take a look to the order of operations .
AND binds more than OR.
In your Snippet 1 the expression is like:
a1 || b1 || (c1 && a2) || b2 || (c2 && a3) || b3 || c3
Your Snippet 2 is like:
(a1 || b1 || c1) && (a2 || b2 || c2) && (a3 || b3 || c3)

#Christoph is right but you also need to add something like !== null after match like
return (typeof a[0] === 'undefined' || a[0] === '' || a[0].match(/^[a-z0-9]+$/i) !==null ) && (typeof a[1] === 'undefined' || a[1] === '' || a[1].match(/^[a-z0-9]+$/i) !== null ) && (typeof a[2] === 'undefined' || a[2] === '' || a[2].match(/^[a-z0-9]+$/i) !== null);
You can take a look at this fiddle http://jsfiddle.net/dv360q1p/1/ which implements your question

Related

How to short the expression?

I have that expression
if (a === Infinity && b === 0 || a === -Infinity && b === 0 || a === 0 && b === Infinity || a === 0 && b === -Infinity) {
return NaN
}
I want short it, but I have no idea how to do this
UPDATE
If it possible, I cant use isFinite(), how to shorten else?
You can use !isFinite() to test if it's either Infinity or -Infinity.
if ((!isFinite(a) && b === 0) || (!isFinite(b) && a === 0)) {
return NaN;
}
If a and b are number typed, then:
if (!(a*b || isFinite(a+b))) return NaN;
If your linter warns about use of global functions, then:
if (!(a*b || Number.isFinite(a+b))) return NaN;
If you can't use multiplication:
if (!(a && b || Number.isFinite(a+b))) return NaN;
Math.absing both and then checking that the minimum is 0 and the maximum is infinity should do it.
const nums = [a, b].map(Math.abs);
if (Math.min(...nums) === 0 && Math.max(...nums) === Infinity) {
return NaN;
}
Can also sort the array.
const nums = [a, b]
.map(Math.abs)
.sort(a, b) => a - b); // .sort() works too, but could be more confusing
if (nums[0] === 0 && nums[1] === Infinity)) {
return NaN;
}

if statement with javascript condition operator

just have 2 question regarding JS conditional operator, is the below 2 expression valid?
1.
if(isUser && isUser === true || isGuest && isGuest === true){
//...
}
I am wondering do I have to add () to make it like and still have the same functioning:
if((isUser && isUser === true) || (isGuest && isGuest === true)){
//...
}
const items = list.orderList && list.orderList.isUser === true || list.orderList.isGuest ? list.items : [];
I am wondering do I have to add () to make it like and functioning the same as above conditional operator:
const items = list.orderList && (list.orderList.isUser === true || list.orderList.isGuest === true) ? list.items : [];
As per Operator Precedence in the MDN docs, logical AND takes precedence over logical OR. Therefore,
expression1 || expression2 && expression3
will evaluate to
expression1 || (expression2 && expression3)
Therefore,
isUser && isUser === true || isGuest && isGuest === true
naturally evaluates to
(isUser && isUser === true) || (isGuest && isGuest === true)
anyway, so you do not need parentheses..
But since, in your second example, you want to evaluate OR then AND, you do need parentheses for it to evaluate the way you require, as
list.orderList && list.orderList.isUser === true || list.orderList.isGuest
will evaluate to
(list.orderList && list.orderList.isUser === true) || list.orderList.isGuest

JavaScript if() statement or/and operators

Can I ask for validation of my statement if is ok and can be refactor?
Condition:
fire if A or B or C are not blank
and D or and E or and F or and G are blank"
if((A !== '' || B !== '' || C !== '') && (D === "" || E === ''
|| F === '' || G === '')){
console.log("fire")
}
You could take just the values of the string variables, like
s !== '' is equal to s
s === '' is equal to !s
if ((A || B || C) && (!D || !E || !F || !G)) {

How can I test two strings for equivalence in JavaScript, considering null and empty string the same?

If I compare "a" and "b", that should be false.
If I compare "a" and "a", that should be true.
If I compare "" and null, that should be true.
I could write my own method, but thought there was perhaps a JavaScript shortcut.
Edit: I was thinking something like this:
areDbSame(s1, s2) {
if (s1 === null) s1 = "";
if (s2 === null) s2 = "";
return s1 === s2;
}
Edit2: Settled on this version:
areDbSame(s1, s2) {
return (s1 === null ? "" : s1) === (s2 === null ? "" : s2);
}
Just before you test the equality of your string, you could do a simple one line enforcement, by converting to '' in the case of null. For example (if you also don't care about undefined, false, etc):
// testString becomes the one you are testing
var testString = myString || '';
If you only want to ensure null is blank
var testString = (myString === null) ? '' : myString;
Then you can simply do your string comparisons using testString, and not worry about the null equalities.
IMO this is the cleanest answer because it doesn't convolute the original equality testing of javascript strings. It is the same as saying, let's split the problem up into two parts.
1) When should my string be considered blank, and
2) Now I can just check for regular string equality.
function areEqualStrings(a, b) {
var otherEqualValues = ['', null];
if(typeof a === 'string' && typeof b === 'string') {
return a === b;
} else if(otherEqualValues.indexOf(a) > -1 && otherEqualValues.indexOf(b) > -1) {
return !a === !b;
} else {
return false;
}
}
When coercing JavaScript values, !null is true and !'' is true, so those would result in being equal.
Here's the test (screenshotted from my console):
This function should do it. It type checks first and short circuits otherwise.
function stringCompare(a, b) {
if (((a === null || typeof a === 'string') ||
(b === null || typeof b === 'string')) &&
((a === '' && b === null) ||
(b === '' && a === null) ||
(a === b))) {
return true;
}
return false;
}
No it hasn`t. The two first cases you can do naturally using operator =.
The third case it is impossible because "" is considered a empty string and null has any type. So they never can be true naturally. To do this, you have to write your own method.
Just to be clear. You can use operators = (equal) to do comparison:
== equal to
`x == 8 false
x == 5 true
x == "5" true
=== equal value and equal type
x === 5 true
x === "5" false
Hope it helps

&& Operator precendence in JavaScript

if(e.FN === ' ' && e.GN === ' ' && e.LN === ' ' && e.DB === ' '){
This condition is never evaluated at all. Is this the way to check if all the values are null.
Right now you are checking if those values are all equal to a Space. The === not only compares the values but ensures they are the same type. However, if e.FN is null both e.FN == ' ' and e.FN === ' " will always return false. I think what you want is
if(e.FN === null && e.GN === null && e.LN === null && e.DB === null)
or even better, if you don't care if they are null, undefined or 0 you could do
if(e.FN && e.GN && e.LN && e.DB)
try:
if(e.FN === null && e.GN === null && e.LN === null && e.DB === null){
To check if all the values are null you should do:
if(e.FN === null && e.GN === null && e.LN === null && e.DB === null){
if the first value is not null javascript doesn't evaluate other condition, because if the first condition is false it's not possible for all the conditions to be true.

Categories