I've been studying JavaScript for a couple months, and I have some questions.
Say we have some if statements like this:
if (something)
if (!something)
From what I have looked up, the first statement checks whether something evaluates to true, whereas the second one checks for whether the condition is not true(I recall reading the ! coerces it into boolean and then 'inverses' it).
However, I'd like to know what are these statements' direct equivalents when not "shortened". I'd like to understand code like this more in depth before really using it.
Is if (something) the same as if (something == true)? Or even if (something === true)?
And what would be the "non-shortened" (for my lack of a better term) direct equivalent of if (!something)?
Thank you for any help.
Part 1:
When we use if(something) javascript will check if it is a 'Truthy' or 'Falsy' value.
So if we say
if(1) {
alert("Yes, it's true...");
}
javscript will check if 1 is a "truthy" value and it is.
Everything that is not a falsy value is truthy by extension.
Falsy values are:
0, 0n, null, undefined, false, NaN, and the empty string “”.
So if we directly put any of the above into a parenthesis it will return false.
e.g. if (null) ... the if clause won't be executed because null is falsy.
Part 2:
When we use if(something == true), we check if one value is equal to another value. If the types are not the same, since we're using == coercion will happen.
What is this about 'coercion'?
If we say if('1' == 1) this will execute the if clause as it returns true. Javascript will convert 1(number) to '1'(string) in this case.
If we want to be strict and say "I only want true if they're both numbers, I don't care if 1 is a string" then we use
if(1 === '1') and this will not execute the if clause(because the condition returns false).
So if we say if(false == false) this will return true because false is equal to false, and the if clause will be executed.
Note the difference if we said if(false) or if('') the if statement will not be executed.
Next, if we want to use negation, we have to put the ! in front of the boolean we're negating, regardless of whether it's part of an if condition or... There is no way around it.
However, there is a shorter version of this:
var a = 3;
var b = 2;
if(a===b) {
alert('A is equal to B');
} else {
alert('B is not equal to A');
}
This is considered shorter(ternary operator):
Note that if we want to use more than one statement, we should use the if else
a = 3;
b = 2;
a===b ? alert('A is equal to B') : alert('B is not equal to A');
Related
The concept of using variables as a while loop test condition is a little confusing to me:
const falsy = "";
while (falsy) {
console.log(1);
}
From what I understand, the test condition 'falsy' doesn't refer to the constant 'falsy' but rather, in it's expanded form, is something like: 'while (falsy === true) {...}'. In this case, since falsy (the constant) evaluates to false, the statement becomes 'while (false === true){...}' which makes the test condition false and the block not execute.
What confuses me is that 'falsy' in the test condition seems to address to two things:
It refers to the actual constant 'falsy' and uses that to evaluate truthiness/falsiness of the test condition
It represents the condition that needs to be satisfied (i.e. falsy as the test condition is testing whether falsy (the constant) is true)
Can anyone confirm my understanding regarding the use of truthy/falsy variables for test conditions?
JavaScript has implicit coercion, in this case one happens to Boolean. It is not equivalent to while (falsy === true), but closer to while (Boolean(falsy)).
See the MDN glossary for the rules.
For example, the following would not print 1 if the test was x === true, however, we say that «x is truthy» because Boolean(x) is true.
const x = ":)";
if (x) {
console.log(1);
}
console.info("To demonstrate,", x === true, Boolean(x));
This question already has answers here:
Empty arrays seem to equal true and false at the same time
(10 answers)
Closed 4 years ago.
I was trying out a code snippet and the results are different for an empty array check inside a console.log statement and in a conditional statement.
Help/Thoughts on why this is different?
Thanks in advance!
//Output: true
if([]) {
console.log(true)
} else{
console.log(false)
}
//Output: false
console.log([] == true)
You seem to be running into a known JavaScript quirk.
"[] is truthy, but not true"
The problem isn't where you are doing the evaluations, but rather that the two evaluations which seem identical are actually different.
See
https://github.com/denysdovhan/wtfjs#-is-truthy-but-not-true
My assumption is that the if/else block, in part of its "truthful" test is checking if something exists (not just if it is true or not) -- wherein the straight console print is comparing the value of the empty array against a boolean (which would be false)
let test = 'apple';
if( test ){
console.log( 'if/else: ' + true );
}else{
console.log( 'if/else: ' + false );
}
console.log( 'log: ' + ( test == true ) );
The two snippets are actually doing different things, hence the different results.
The first, with [] as the condition of the if statement, coerces the array to a Boolean value. (if, naturally enough, only works on Booleans, and JS will happily convert the given value if it isn't already Boolean.) This produces true - all objects in JS are "truthy", which includes all arrays.
For the second snippet, you are using the "loose equality" operator == - for which the JS specification provides a set of rules for how to convert the values into other types, eventually reaching a straightforward comparison between two values of the same type. You might want, or hope, that comparing a non-Boolean to true or false in this situation coerced the non-Boolean to Boolean - but this isn't what happens. What the specification says is that first the Boolean is coerced to number value - resulting in 1 for true (and 0 for false). So it reduces to [] == 1 - which will go through a few more conversions before resulting in a false result.
The key point is that no conversion to Boolean happens in the second case. If you think this is stupid, you're probably right. This is a bit of a gotcha, and one of the reasons many guides tell you never to use == in JS. I don't actually agree with that advice in general (and hate linters telling me to always use === in any circumstances) - but you do have to be aware of some dangers. And using == to compare a value to true or false is something to always avoid.
Luckily, if you want to test if x is truthy or falsy, you have a very short and understandable way to do it - the one you used in the first snippet here: if (x)
[edit] So my original answer was confusing as heck, and there are some incongruencies in the many answers you find on this subject all over the internet; so, let me try this again:
Part 1: Why they are Different
if([]) and if([] == true) are not the same operation. If you see the below example, you will get the same result when doing the same operation.
//Output: false
if([] == true) {
console.log(true);
} else{
console.log(false);
}
//Output: false
console.log([] == true);
Part 2: Why it matters AKA: the confusing bits
In JS, the following is a common expression used to see if an object/variable exists:
var foo = "Hello World";
if (foo) ...
From a design perspective, this test is not important to see if foo is equal to true or false, it is a test to see if the program can find the object or variable foo. If it finds foo, then it executes the results in the "then" condition, otherwise you get the "else" condition. So, in this case, it will convert foo to either false for does not exist, or true for does exist. So in this case the string is reduced to a boolean.
In contrast:
var foo = "Hello World";
if (foo == true) ...
Is typically trying to find out if the value of foo actually equals true. In this case, you are comparing the value of foo "Hello World" to a boolean, so in this case, "Hello World" does not equal true.
Just like foo, [] can be evaluated more than one way. An empty array is still an object; so, in the first case, it coerces to true because it wants to know if [] can be found; however, [] also equals ['']. So now picture this:
if (['bar'] == 'bar') ...
In this case, JS will not look at ['bar'] to see if it is there, but as an object containing a single value which it can convert to the string, 'bar'.
So:
if([]); // is true because it is an object test that evaluates as (1 === 1)
and
if([] == true) // is false because it is a string test that evaluates as ('' == 1) to (0 === 1)
Let me start off by saying I understand the difference between =, ==, and
===. The first is used to assign the right-hand value to the left-hand variable, the second is used to compare the equivalency of the two values, and the third is used not just for equivalency but type comparison as well (ie true === 1 would return false).
So I know that almost any time you see if (... = ...), there's a pretty good chance the author meant to use ==.
That said, I don't entirely understand what's happening with these scripts:
var a = 5;
if (a = 6)
console.log("doop");
if (true == 2)
console.log('doop');
According to this Javascript type equivalency table, true is equivalent to 1 but not 0 or -1. Therefore it makes sense to me that that second script does not output anything (at least, it isn't in my Chrome v58.0.3029.110).
So why does the first script output to the console but the second doesn't? What is being evaluated by the first script's if statement?
I dug into my C# knowledge to help me understand, but in C# you cannot compile if (a = 5) Console.WriteLine("doop"); so I had to explicitly cast it to a bool by doing if (Convert.ToBoolean(a = 5)) but then that makes sense it would evaluate to true because according to MSDN's documentation, Convert.ToBool returns true if the value supplied is anything other than 0. So this didn't help me very much, because in JS only 1 and true are equal.
There's a difference between making an abstract equality comparison with == and performing a simple type cast to boolean from a number value. In a == comparison between a boolean and a number, the boolean value is converted to 0 or 1 before the comparison. Thus in
if (true == 2)
the value true is first converted to 1 and then compared to 2.
In a type cast situation like
if (x = 2)
the number is converted to boolean such that any non-zero value is true. That is, the value 2 is assigned to x and the value of the overall expression is 2. That is then tested as boolean as part of the evaluation of the if statement, and so is converted as true, since 2 is not 0.
The various values that evaluate to boolean false are 0, NaN, "", null, undefined, and of course false. Any other value is true when tested as a boolean (for example in an if expression).
Why does an assignment in an if statement equate to true?
It doesn't. An assignment is evaluated as whatever value is assigned.
This expression is a true value:
a = true
But this expression is a false value:
b = false
That's true whether or not you put it in an if statement or not.
In javascript, which will be better way to check conditional statement in terms of performance, robustness and which is the best practice?
var x = null;
// this condition is checked frequently and x will be set to null or some value accordingly
if(x !== null){...}
OR
if(!!x){...}
You could just do
if (x) { ... }
Simply says, if x is a truthy value.
As Nina pointed out. I would always add some extra validation, depending on what I'm expecting.
if (x && x > 0) { ... }
Or
if (x && x instanceof Array)
But I'm always checking x has some sort of value and isn't undefined or null
It's never necessary to write if(!!x){...}. That is exactly the same thing as writing if(x){...}. Using the ! operator twice converts a value to a boolean that reflects whether it is "truthy" or not. But the if statement does that anyway: it tests whether the value you provide is "truthy". So whether you use !! or not it will do the same thing.
if(x !== null){...} is something else entirely. It doesn't just check whether x is "truthy", it specifically compares the value of x with null. For example, if x has the numeric value 0, if(x){...} or if(!!x){...} will not execute the ... code, because 0 is a "falsy" value, but if(x!==null) will execute the ... code, because 0 is not the same value as null.
A related example is if(x!=null){...} or if(x==null){...}. (Note the use of != or == instead of !== or ===.) This is a bit of a special case in JavaScript. When you compare against null using the != or == operator, it actually compares against either null or undefined and treats those two values the same. In other words, if x is either null or undefined, then if(x==null){...} will execute the ... code, but if(x!=null){...} will not execute the ... code.
It's generally recommended to avoid the == and != operators and use the strict comparison === or !== instead, but treating null and undefined the same can be useful in some situations, so this is a case where the non-strict operators are helpful.
In any case, the real question to ask is what is the purpose of your code, and what specifically do you need to test for here?
Assuming you need to check for a value which is strict inequality !== to null
this condition is checked frequently and x will be set to null or some value accordingly
if (x !== null) { /* */ }
Then you can only use the above comparison. Any other comparison would return a wrong result.
For example
var x = 0;
if (x !== null) { // true
console.log(x + ' !== null');
}
if (x) { // false
console.log(x);
}
// some more checks
console.log(undefined !== null); // true
console.log(undefined != null); // false
Edit: My response was quite wrong which I learned after my conversation with Nina Scholz in her own response to this thread. I updated accordingly.
There are many ways to check values depending on the type you expect to use. Therefore the problem is not so much about performance as it is with correct evaluation. Starting with your examples:
if(x != null)
This will evaluate to false if the value of x is either null or `undefined'.
The next case:
if(!!x)
This is an entirely different operation. It casts the value of x as a boolean, and in most cases if(x) will work the same way. But now, if the value is falsy, like 0, the empty string, the expression returns false. So, if expecting a number, you should check for the zero value:
if(x || (0 === x))
Bear in mind that if x were anything other than an int, the expression returns true.
And the case where you expect a string:
if(x || ('' === x))
Same thing here, if x was, say 12, the expression returns true.
I could go on with lots of examples. Unfortunately there are certain expressions that work in unexpected ways. For instance, it should be easy to check if a value is a number by calling isNaN(number), but if the value is an empty string or a representation of an array index ('2'), isNaN returns false.
I recommend you to check this table with all the type conversions so that you become more aware on how to check the validity of a value.
This question already exists:
Closed 12 years ago.
Possible Duplicate:
In Javascript, what does it mean when there is a logical operator in a variable declaration?
Stumbled across this code online, have no idea what it does, wasn't able to find out with FireBug either, and I can't google it because of the special characters...
var myValue = myInput.value || 0;
if myInput.value is undefined (or another falsy value) then the default value of 0 will be set
some examples...
myInput.value = undefined
var myValue = myInput.value || 0;
// myValue = 0
myInput.value = 10
var myValue = myInput.value || 0;
// myValue = 10
|| is often called the default operator. It lets you give a default value, if something else is falsy. So if myInput.value is undefined, for example, myValue will be assigned 0.
Because of the way the javascript interpreter is built, it can interpret certain classes of values or even the existence (or non-existence) of values as true or false
undefined, null, false, 0, empty string, NaN can be interpreted as false
the existence of a non-false value can be interpreted as not-false, thus in many cases, true; Don't confuse not-false with true though. They are sometimes loosely interpreted as the same, but not-false contains everything that isn't interpreted as false, whereas true is much more specific.
Thus:
if (myMethod)
myMethod();
Can be used to check for the existence of myMethod before running it.
The || symbol is a short-circuiting OR statement. If the first part of the OR is or can be interpreted as not-false, then that part of the statement will preside and the value will be taken and used as myValue. If javascript deems that the first part of the statement is interpreted as false, then the second part of the OR will be returned.
Thus in the statement:
var myValue = myInput.value || 0;
myValue will become whatever myInput.value contains if it contains anything that javascript can interpret as not false. Thus it could contain "Hi, hell of a day we've got here!" and that would be returned to myValue.
When I say not-false, I don't strictly mean true, because "Hi, hell of a day we've got here" isn't [strictly speaking] interpreted as true, but is "coerced" to being interpreted that way.
If myInput.value doesn't contain anything that javascript could coerce to being interpreted as true, then 0 will be returned to myValue.
So in this case, if myInput.value is undefined, null, false, 0 etc. then myValue = 0
It's a way of having a default value of 0 in case myInput.value is null (undefined)
Javascript has a defined left to right evaluation order. So if you write something like
if (method() || method2()) { ... }
method2() will never happen if method() returns true, because true OR anything will always be true.
This works the same for the example you are giving in Javascript.
If "myinput.value" evaluates to something trueish, this value will be assigned, otherwise 0 will be assigned for every falsish value (null, 0, "").
It sets myValue to the value of myInput or to 0, if the myInput value is anything that’s considered false in JavaScript (especially undefined or null). The trick is the short-circuit behaviour of the || operator. When you evaluate a||b and a is true, the || operator returns a:
console.log('a'||'b'); // 'a'
When the first argument is false, the || operator returns its second argument:
console.log(undefined||'b'); // 'b'
It’s also good to ponder this:
var foo = 0;
console.log('a'||foo++);
console.log(foo); // 0
console.log(undefined||foo++); // 0
console.log(foo); // 1
The || operator in many langiages includes an optimization called short-cutting: if the left side evaluates to a true value then the right side does not need to be evaluated. True || anything == true. This is often used to provide default values, as in your example code. If the left hand side myInput.value evaluates to true, then the whole expression will return that value. Otherwise, the whole expression will return the right hand value of 0.
Note that this also depends on the || operator returning the original values rather than a boolean true or false value. Each side is evaluated to true or false for the logic test, but not for the expression's return value.
function or(a, b) {
if (a) { return a; }
return b;
}
MyValue will be equal to myInput.value OR 0 if the previous value can be regarded as False.
Value can be regarded as False is its empty string (''), zero (0) etc. Anything that say True in this code myInput.value == False
It means that if myInput.value isn't defined, myValue will be set to 0. Think || same as OR.