What's the difference between & and && in JavaScript?
Example code:
var first = 123;
var second = false;
var third = 456;
var fourth = "abc";
var fifth = true;
alert(first & second); // 0
alert(first & third); // 72
alert(first & fourth); // 0
alert(first & fifth); // 1
alert(first && second); // false
alert(first && third); // 456
alert(first && fourth); // abc
alert(first && fifth); // true
It seems like && is a logical and which gives me always the second value if both are true.
But what is &?
(By the way, && seems to be and in Python; & seems to be & in Python)
& is bitwise AND
This operator is almost never used in JavaScript. Other programming languages (like C and Java) use it for performance reasons or to work with binary data. In JavaScript, it has questionable performance, and we rarely work with binary data.
This operator expects two numbers and retuns a number. In case they are not numbers, they are cast to numbers.
How does it work? Wikipedia has an answer: https://en.wikipedia.org/wiki/Bitwise_operation#AND
&& is logical AND
Most usually, programmers use this operator to check if both conditions are true, for example:
true && true // returns true
true && false // returns false
However, in JavaScript, it is extended to allow any data type and any number of terms. It returns:
First term that evaluates to false
Last term otherwise (if all are true-y)
Here are some examples:
true && false && true // returns false
true && 20 && 0 && false // returns 0 (it is first false-y)
10 && "Rok" && true && 100 // returns 100 (as all are true-y)
&& short-circuiting
As can be seen from above, as soon as you find one that term is false-y, you needn't to care about the following terms. This allows Javascript to stop evaluation altogether. This is called short circuiting.
This statement doesn't alert anything and false is returned:
true && false && alert("I am quiet!") // returns false
Therefore, you could use the && operator as a shorter replacement for an if statement. These are equivalent:
if (user.isLoggedIn()) alert("Hello!")
user.isLoggedIn() && alert("Hello!")
Almost all JS compressors use this trick to save 2 bytes.
& is the bitwise "and". This means that if you have two numbers converted to binary, the result is a number that has the 1 digit at the positions where both numbers have 1.
100011 //35
& 111001 //57
---------
100001 //35 & 57 == 33
To determine whether two boolean values put together are true or false, if you want to check them both (like validation on the web page), you may use the & operator. & is bitwise AND.
With the && operator, once it finds the first value is false, it will end evaluation and not to check the second value.
With all the lofty, detailed insights throughout, they have mostly missed the truth that there is a conditional evaluation where ONLY the single & will work. The practical layman's answer that solved my head beating on an IF statement string of MULTIPLE chained && each !== to a condition was causing FAILURE and needed to legitimately use the single &. I thank Jake Wayne (and Russ) for their unfairly downvoted answer that got it right given that where there is more than one && that !== it has already ceased its evaluation and proceeds no further after the first evaluation is found ==!. With the && it thinks its job is done after the first evaluation shows !== [eg. false]. My failing code was
IF ((sessionStorage.myLable !== "LableStringA") && (sessionStorage.myLable !== "LableStringB") && (sessionStorage.myLableZ !== "LableStringA") && (sessionStorage.myLableZ !== "LableStringB")) { ...)
Here, properly substituting and using a single & for the && it was both practically in the real world and technically the correct answer. Thank you again Jake Wayne (and Russ) for the insight and understanding of code.
Related
I'm pretty new to Javascript and React, so please bear with me.
I have a component in my app, that is taking a timespan from the user, but now I want to calculate the price the user would have to pay, depending on their input. I figured that it would probably be the easiest way to use an if loop but something is very off with that and I am a little stuck.
Is my attempt okay in general or does it need a separate function that I have to call in order to do what I want to do?
onConfirm(hour, minute) {
this.setState({ time: `Dauer: ${hour}:${minute}` });
this.setState(if((hour) < 4){return price = `Preis: (${hour}* 1.5) €`;}
else {return price= 'Preis: 5.50 €';} );
this.TimePicker.close();
}
Within an object literal, you can't use statements, only expressions. if is a statement.
If you want to do that either/or logic in an expression, you use the conditional operator (? :), like this:
onConfirm(hour, minute) {
this.setState({
time: `Dauer: ${hour}:${minute}`,
price: hour < 4 ? `Preis: (${hour}* 1.5) €` : 'Preis: 5.50 €'
});
this.TimePicker.close();
}
The conditional operator expression in the above is:
hour < 4 ? `Preis: (${hour}* 1.5) €` : 'Preis: 5.50 €'
It's a ternary operator (an operator accepting three operands):
The condition to test (hour < 4)
The expression to evaluate if the condition is truthy¹ (`Preis: (${hour}* 1.5) €`)
The expression to evaluate if the condition is falsy¹ ('Preis: 5.50 €')
Also note you had a closing ' on a template literal (needed a backtick instead).
¹ "truthy" and "falsy" - JavaScript implicitly converts (or coerces) values. When you use a value as a test, such as in an if or a conditional operator, JavaScript converts the value you provide to a boolean value (true or false). Values that convert to true are called "truthy" values, ones that convert to false are called "falsy." The falsy values are NaN, null, undefined, 0, "", and of course false (on browsers, document.all is also falsy for various reasons I explain in my book). All other values are truthy.
Essentially what I'm attempting to do is circumvent when users enter a number in a non-standard format. For example:
1.5 million should be 1500000
Previous Zap step extracts the number using the Formatter > Extract Number function. So the result is the variable rawNum and the original number is noformatNum.
var str = inputData.noformatNum;
var n = inputData.noformatNum.includes ("million");
if (n = true) return {
finalNum: Number(inputData.rawNum) * 1000000
};
else return { finalNum : inputData.noformatNum };
It works in that it completes the operation and turns 1.5 to 1500000, but it executes each time, even if noformatNum doesn't include "million" in the string. I'm not super experienced with Javascript, but after digging around W3C and the Zapier documentation for a couple hours I'm stumped. Any help is much appreciated. Thanks!
It looks like there's a small but significant syntax issue here. You'll want to use a triple equal sign === instead of a single = in your conditional.
if (n = true) return {
should be
if (n === true) return {
In an if...else statement, the part in parenthesis (the "condition") should be something that evaluates to either a "truthy" or "falsy" value. (MDN)
n = true assigns the value of true to the variable n, so JavaScript considers the whole thing "truthy" no matter what.
n === true compares n to true, which is what you want for the if...else statement to work. The value will be "truthy" or "falsy" depending on the value of n.
I am curious as to why this while loop is not breaking as expected. It is my understanding that when using the OR operator (||), if any of the conditions are found to be false, the loop breaks.
However, I noticed in a test document (I am learning JS for the first time) that my while loop is requiring ALL conditions to be found false before breaking.
This is a stub example:
var stringName="", numhours=0, numRate=0;
document.write("Exit at any time by entering -1");
while (stringName != "-1" || numHours != -1 || numRate != -1){
stringName = prompt("Enter name","");
numHours = prompt("Enter num hours","");
numHours = parseFloat(numHours);
numRate = prompt("Enter rate per hour","");
numRate = parseFloat(numRate);
}
I would like it so that a user can enter -1 at any stage, and once the loop completes, it will re-check the conditions again, and after finding that the it is false that the name does not equal "-1", or false that the hours does not equal -1, or that it is false that the wage does not equal -1, it will break the loop.
Instead, it seems the loop is requiring that all of those conditions are met to exit, where name == "-1" AND hours == -1 AND wage == -1, only then will it break.
Any insight would be appreciated. You guys rock!
You have your understanding of the OR operator backwards. You're treating it like AND.
Instead of:
It is my understanding that when using the OR operator (||), if any of the conditions are found to be false, the loop breaks.
It's actually
If any of the conditions are found to be true, the loop continues.
To fix the problem you can rewrite your loop to be:
while (stringName !== "-1" && numHours !== -1 && numRate !== -1)
Also it is preferable to use !== instead of != because != does something weird called type coercion that can give you results you don't expect.
You have it backwards. The || operator evaluates to true if either operand has a "truthy" value (true, non-null, etc.). Your while loop will exit only when all the individual inequality tests are false. If you want it to exit when any of them is false, use the && operator instead.
while(condition) will loop until condition == false.
Your question can be answered when we test this using the console:
true||false||false||false||true will evaulate to true
since OR statements evaluate to true if any one of their conditions are true.
Logical OR Operator
I am peer reviewing code written in vanilla javascript, and one of the authors occasionally performs a lazy-typecast if statement because he is evaluating values from a REST service that has very sloppy data. Occasionally a value representing money in USD comes back as a string, and sometimes as a number, probably depending on what validation was in place at the time the user entered the data over the years.
So sometimes we get a value of 150 and sometimes we get "150" (without the quotes, if you know what I mean).
The data is just displayed, and there are no math operations done against it: it simply needs to be compared to another number so some display styling can be done.
Instead of writing some function that checks the type of data and forces it to be a uniform type, the developer does something like this:
var baseVal = ReturnsAnIntegerValue(); // returns a number
var retrievedVal = CallToAwfulDataService(); // could return number or string
if (retrievedVal && retrievedVal == baseVal) {
// do stuff
}
else { ...
At first the == made me see a red flag, but when I asked him about it, he said that the initial check for if (retrievedVal && ... would prevent unexpected outcomes from situations where baseVal and retrievedVal are each some combination of null, 0, empty string, or undefined, like this:
if (null && null == undefined) // false | if (null == undefined) // true
if (0 && 0 == "") // false | if (0 == "") // true
if (0 && 0 == "0") // false | if (0 == "0") // true
if (0 && 0 == "") // false | if (0 == "") // true
You get the idea. I feel like this should be bad code because I was taught that the == is bad form, but the code is readable and concise, without the need for an extra function that type-converts just for show. I can't think of a scenario where we are likely to be hurt by it.
Is this bad code? Specifically: what is wrong with it? Is there a better practice for handling this?
edit
I forgot to mention, I have looked at a bunch of SO questions that mostly seem to back up the == is code smell school of thought, but I can't see what is technically risky about this scenario.
You should probably have some "normalize" function, and test cases with data samples from the backend.
Good practices generally assume that "all is fine" with the environment, which isn't your case.
Which ever way you go, you're doomed as far as "good practices" are concerned.
Before anyone jumps in to answer and bash me for asking a silly question; I'm aware of what the not operator does, at least in other languages it should invert a result from true to false and vice versa. The thing I'm stuck on is the strange behavior I get from time to time. I.e. I had this in my code. It's not doing what I expect it to do.
_checkOnOff: function(inst) {
return (!$.suggestBox.onOff || !$.suggestBox._get(inst, 'onOff')) ? false : true;
},
The actual values for the 'onOff' variables that I'm dealing with here are 0 and 1. I'm assuming that the '!' operator will reverse them.
However I couldn't get it to work until I changed the function to explicitly state '== 0' like so...
_checkOnOff: function(inst) {
return ($.suggestBox.onOff == 0 || $.suggestBox._get(inst, 'onOff') == 0) ? false : true;
},
Edit: Added info Both $.suggestBox.onOff and $.suggestBox._get(inst, 'onOff') will be either 0 or 1.
My question is why didn't !$.suggestBox.onOff produce true when $.suggestBox.onOff was equal to 0? Is Javascript ! equivalant to the bitwise operator?
Edit: Second attempt
I tried using '!!' like was suggested (to get a bool) and found nothing changed. Here is the code and outputs:
console.log('val: ' + $.suggestBox.onOff); // outputs: 0
console.log('! : ' + !$.suggestBox.onOff); // outputs: false
console.log('!! : ' + !!$.suggestBox.onOff); //outputs: true
console.log('!!! : ' + !!!$.suggestBox.onOff); //outputs: false
The output doesn't change if $.suggestBox.onOff is 1 or 0!!! it's still false, true, false. What is going on?!
Edit: Third attempt I found out that it has something to do with my variable. I don't know how, but it has to do with the way that it has been set. Ok, prepare yourselves, what I'm about to tell you, may very well blow your mind and change the way you type on the keyboard. It's that incredible:
//this.onOff = 0;
console.log('this.onOff: ' + this.onOff); //output: 0
console.log('! : ' + ! this.onOff); //output: false
console.log('!! : ' + !! this.onOff); //output: true
If I uncomment out the 'this.onOff = 0', thereby explicitly assigning this.onOff to a literal, it changes the output to:
0
true
false
I just found out why. I will write it down in the answer section. Small clue is that it's the way the variable $.suggestBox.onOff was set.
It seems that $.suggestBox.onOff is set with "0" as a string, which in JavaScript is always truthy.
Since "0" is truthy and 0 is falsy, you'd expect 0 == "0" to be false, but it's not.
Try the following in your console:
!! "0"; // true
!! 0; // false
0 == "0"; // true
Weird? Yes. Welcome to the awkward world of JavaScript!
To get around this issue, you should either have $.suggestBox.onOff be an actual number, or convert it on the fly:
_checkOnOff: function(inst) {
return !! ( +$.suggestBox.onOff && +$.suggestBox._get(inst, 'onOff') );
}
Update: Since you pointed out in the comments that you're setting it by a text value, use this when setting it so that it's always set as a number:
$.suggestBox.onOff = +$(this).val();
I think you're confused, because you're negating a string, not a number. Strings are a bit different and handled a bit funny when it comes to their evaluation as a boolean.
!0
is true, as expected.
!"0"
is false... so, the question, is "0" truthy?
I wish I had a better source (sitepoint isn't bad, but it's not as authoritative as a w3 document), but, according to http://www.sitepoint.com/javascript-truthy-falsy/
The following values are always falsy:
false
0 (zero)
"" (empty string)
null
undefined
NaN (a special Number value meaning Not-a-Number!)
All other values are truthy, including
"0" (zero in quotes), "false" (false in quotes), empty functions,
empty arrays, and empty objects.
So, what you are seeing is indeed expected.