Why does an assignment in an if statement equate to true? - javascript

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.

Related

Difference between using logical expression in includes or outside of that [duplicate]

I know that in JavaScript you can do:
var oneOrTheOther = someOtherVar || "these are not the droids you are looking for...";
where the variable oneOrTheOther will take on the value of the first expression if it is not null, undefined, or false. In which case it gets assigned to the value of the second statement.
However, what does the variable oneOrTheOther get assigned to when we use the logical AND operator?
var oneOrTheOther = someOtherVar && "some string";
What would happen when someOtherVar is non-false?
What would happen when someOtherVar is false?
Just learning JavaScript and I'm curious as to what would happen with assignment in conjunction with the AND operator.
Basically, the Logical AND operator (&&), will return the value of the second operand if the first is truthy, and it will return the value of the first operand if it is by itself falsy, for example:
true && "foo"; // "foo"
NaN && "anything"; // NaN
0 && "anything"; // 0
Note that falsy values are those that coerce to false when used in boolean context, they are null, undefined, 0, NaN, an empty string, and of course false, anything else coerces to true.
&& is sometimes called a guard operator.
variable = indicator && value
it can be used to set the value only if the indicator is truthy.
Beginners Example
If you are trying to access "user.name" but then this happens:
Uncaught TypeError: Cannot read property 'name' of undefined
Fear not. You can use ES6 optional chaining on modern browsers today.
const username = user?.name;
See MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining
Here's some deeper explanations on guard operators that may prove useful in understanding.
Before optional chaining was introduced, you would solve this using the && operator in an assignment or often called the guard operator since it "guards" from the undefined error happening.
Here are some examples you may find odd but keep reading as it is explained later.
var user = undefined;
var username = user && user.username;
// no error, "username" assigned value of "user" which is undefined
user = { username: 'Johnny' };
username = user && user.username;
// no error, "username" assigned 'Johnny'
user = { };
username = user && user.username;
// no error, "username" assigned value of "username" which is undefined
Explanation: In the guard operation, each term is evaluated left-to-right one at a time. If a value evaluated is falsy, evaluation stops and that value is then assigned. If the last item is reached, it is then assigned whether or not it is falsy.
falsy means it is any one of these values undefined, false, 0, null, NaN, '' and truthy just means NOT falsy.
Bonus: The OR Operator
The other useful strange assignment that is in practical use is the OR operator which is typically used for plugins like so:
this.myWidget = this.myWidget || (function() {
// define widget
})();
which will only assign the code portion if "this.myWidget" is falsy. This is handy because you can declare code anywhere and multiple times not caring if its been assigned or not previously, knowing it will only be assigned once since people using a plugin might accidentally declare your script tag src multiple times.
Explanation: Each value is evaluated from left-to-right, one at a time. If a value is truthy, it stops evaluation and assigns that value, otherwise, keeps going, if the last item is reached, it is assigned regardless if it is falsy or not.
Extra Credit: Combining && and || in an assignment
You now have ultimate power and can do very strange things such as this very odd example of using it in a palindrome.
function palindrome(s,i) {
return (i=i || 0) < 0 || i >= s.length >> 1 || s[i] == s[s.length - 1 - i] && isPalindrome(s,++i);
}
In depth explanation here: Palindrome check in Javascript
Happy coding.
Quoting Douglas Crockford1:
The && operator produces the value of its first operand if the first operand is falsy. Otherwise it produces the value of the second operand.
1 Douglas Crockford: JavaScript: The Good Parts - Page 16
According to Annotated ECMAScript 5.1 section 11.11:
In case of the Logical OR operator(||),
expr1 || expr2 Returns expr1 if it can be converted to true;
otherwise, returns expr2. Thus, when used with Boolean values, ||
returns true if either operand is true; if both are false, returns
false.
In the given example,
var oneOrTheOther = someOtherVar || "these are not the droids you are looking for...move along";
The result would be the value of someOtherVar, if Boolean(someOtherVar) is true.(Please refer. Truthiness of an expression). If it is false the result would be "these are not the droids you are looking for...move along";
And In case of the Logical AND operator(&&),
Returns expr1 if it can be converted to false; otherwise, returns
expr2. Thus, when used with Boolean values, && returns true if both
operands are true; otherwise, returns false.
In the given example,
case 1: when Boolean(someOtherVar) is false: it returns the value of someOtherVar.
case 2: when Boolean(someOtherVar) is true: it returns "these are not the droids you are looking for...move along".
I see this differently then most answers, so I hope this helps someone.
To calculate an expression involving ||, you can stop evaluating the expression as soon as you find a term that is truthy. In that case, you have two pieces of knowledge, not just one:
Given the term that is truthy, the whole expression evaluates to true.
Knowing 1, you can terminate the evaluation and return the last evaluated term.
For instance, false || 5 || "hello" evaluates up until and including 5, which is truthy, so this expression evaluates to true and returns 5.
So the expression's value is what's used for an if-statement, but the last evaluated term is what is returned when assigning a variable.
Similarly, evaluating an expression with && involves terminating at the first term which is falsy. It then yields a value of false and it returns the last term which was evaluated. (Edit: actually, it returns the last evaluated term which wasn't falsy. If there are none of those, it returns the first.)
If you now read all examples in the above answers, everything makes perfect sense :)
(This is just my view on the matter, and my guess as to how this actually works. But it's unverified.)
I have been seeing && overused here at work for assignment statements. The concern is twofold:
1) The 'indicator' check is sometimes a function with overhead that developers don't account for.
2) It is easy for devs to just see it as a safety check and not consider they are assigning false to their var. I like them to have a type-safe attitude, so I have them change this:
var currentIndex = App.instance && App.instance.rightSideView.getFocusItemIndex();
to this:
var currentIndex = App.instance && App.instance.rightSideView.getFocusItemIndex() || 0;
so they get an integer as expected.

Javascript difference between if(id != null) vs if(!id) [duplicate]

I just learned there are truthy and falsy values in python which are different from the normal True and False.
Can someone please explain in depth what truthy and falsy values are? Where should I use them? What is the difference between truthy and True values and falsy and False values?
We use "truthy" and "falsy" to differentiate from the bool values True and False. A "truthy" value will satisfy the check performed by if or while statements. As explained in the documentation, all values are considered "truthy" except for the following, which are "falsy":
None
False
Numbers that are numerically equal to zero, including:
0
0.0
0j
decimal.Decimal(0)
fraction.Fraction(0, 1)
Empty sequences and collections, including:
[] - an empty list
{} - an empty dict
() - an empty tuple
set() - an empty set
'' - an empty str
b'' - an empty bytes
bytearray(b'') - an empty bytearray
memoryview(b'') - an empty memoryview
an empty range, like range(0)
objects for which
obj.__bool__() returns False
obj.__len__() returns 0, given that obj.__bool__ is undefined
As the comments described, it just refers to values which are evaluated to True or False.
For instance, to see if a list is not empty, instead of checking like this:
if len(my_list) != 0:
print("Not empty!")
You can simply do this:
if my_list:
print("Not empty!")
This is because some values, such as empty lists, are considered False when evaluated for a boolean value. Non-empty lists are True.
Similarly for the integer 0, the empty string "", and so on, for False, and non-zero integers, non-empty strings, and so on, for True.
The idea of terms like "truthy" and "falsy" simply refer to those values which are considered True in cases like those described above, and those which are considered False.
For example, an empty list ([]) is considered "falsy", and a non-empty list (for example, [1]) is considered "truthy".
See also this section of the documentation.
Python determines the truthiness by applying bool() to the type, which returns True or False which is used in an expression like if or while.
Here is an example for a custom class Vector2dand it's instance returning False when the magnitude (lenght of a vector) is 0, otherwise True.
import math
class Vector2d(object):
def __init__(self, x, y):
self.x = float(x)
self.y = float(y)
def __abs__(self):
return math.hypot(self.x, self.y)
def __bool__(self):
return bool(abs(self))
a = Vector2d(0,0)
print(bool(a)) #False
b = Vector2d(10,0)
print(bool(b)) #True
Note: If we wouldn't have defined __bool__ it would always return True, as instances of a user-defined class are considered truthy by default.
Example from the book: "Fluent in Python, clear, concise and effective programming"
Truthy values refer to the objects used in a boolean context and not so much the boolean value that returns true or false.Take these as an example:
>>> bool([])
False
>>> bool([1])
True
>>> bool('')
False
>>> bool('hello')
True
Where should you use Truthy or Falsy values ?
These are syntactic sugar, so you can always avoid them, but using them can make your code more readable and make you more efficient.
Moreover, you will find them in many code examples, whether in python or not, because it is considered good practice.
As mentioned in the other answers, you can use them in if tests and while loops. Here are two other examples in python 3 with default values combined with or, s being a string variable. You will extend to similar situations as well.
Without truthy
if len(s) > 0:
print(s)
else:
print('Default value')
with truthy it is more concise:
print(s or 'Default value')
In python 3.8, we can take advantage of the assignment expression :=
without truthy
if len(s) == 0:
s = 'Default value'
do_something(s)
with truthy it is shorter too
s or (s := 'Default value')
do_something(s)
or even shorter,
do_something(s or (s := 'Default value'))
Without the assignment expression, one can do
s = s or 'Default value'
do_something(s)
but not shorter. Some people find the s =... line unsatisfactory because it corresponds to
if len(s)>0:
s = s # HERE is an extra useless assignment
else:
s = "Default value"
nevertheless you can adhere to this coding style if you feel comfortable with it.
Any object in Python can be tested for its truth value. It can be used in an if or while condition or as operand of the Boolean operations.
The following values are considered False:
None
False
zero of any numeric type, for example, 0, 0L, 0.0, 0j.
any empty sequence, for example, '', (), [].
any empty mapping, for example, {}.
instances of user-defined classes, if the class defines a __nonzero__() or __len__() method, when that method returns the integer zero or bool value False.
All other values are considered True -- thus objects of many types are always true.
Operations and built-in functions that have a Boolean result always return 0 or False for false and 1 or True for true, unless otherwise stated.
In case of if (!id) {}
!expr returns false if its single operand can be converted to true; otherwise, returns true.
If a value can be converted to true, the value is so-called truthy. If a value can be converted to false, the value is so-called falsy.
Examples of expressions that can be converted to false are:
null;
NaN;
0;
empty string ("" or '' or ``);
undefined.
Even though the ! operator can be used with operands that are not Boolean values, it can still be considered a boolean operator since its return value can always be converted to a boolean primitive. To explicitly convert its return value (or any expression in general) to the corresponding boolean value, use a double NOT operator or the Boolean constructor.
Example:
n1 = !null // !t returns true
n2 = !NaN // !f returns true
n3 = !'' // !f returns true
n4 = !'Cat' // !t returns false
While in case of if (id != null) {} it will only check if the value in id is not equal to null
reference https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_NOT
Falsy means something empty like empty list,tuple, as any datatype having empty values or None.
Truthy means :
Except are Truthy

why this code is not working as expected?

let x;
console.log("shubham" == true ); // gives false
"shubham" ? x=2 : x=3;
console.log(x); // gives 2, so "shubham" must be true?
//I am hoping to get value 3
when you use this:
"shubham" == true
before comparing, true turned to 1,so the actually comparsion is
"shubham" == 1
so ,it gives false;
the book:
When performing conversions, the equal and not-equal operators follow
these basic rules:
If an operand is a Boolean value, convert it into a
numeric value before checking for equality. A value of false converts
to 0, whereas a value of true converts to 1.
If one operand is a string and the other is a number, attempt to convert the string into a number before checking for equality.
when you use this:
"shubham" ? x=2 : x=3;
works like:
Boolean("shubham")?x=2:x=3
so,it gives you x=2;
the book:
variable = boolean_expression ? true_value : false_value;
This basically allows a conditional assignment to a variable depending
on the evaluation of the boolean_expression. If it’s true, then
true_value is assigned to the variable; if it’s false, then
false_value is assigned to the variable.
the book:
Professional JavaScript for Web Developers.3rd.Edition.Jan.2012
Yes, this is due to the underlying code behind the 'if' statement in Javascript. It relies on a method 'ToBoolean' which converts the condition of the if statement to a boolean value. Any string that is not empty, is converted to true. Thus, why you get the above logic.

Can someone explain this 'double negative' trick? [duplicate]

This question already has answers here:
What is the !! (not not) operator in JavaScript?
(42 answers)
Closed 8 years ago.
I am by no means an expert at Javascript, but I have been reading Mark Pilgrim's "Dive into HTML5" webpage and he mentioned something that I would like a better understanding of.
He states:
Finally, you use the double-negative trick to force the result to a Boolean value (true or false).
function supports_canvas() {
return !!document.createElement('canvas').getContext;
}
If anyone can explain this a little better I would appreciate it!
A logical NOT operator ! converts a value to a boolean that is the opposite of its logical value.
The second ! converts the previous boolean result back to the boolean representation of its original logical value.
From these docs for the Logical NOT operator:
Returns false if its single operand can be converted to true; otherwise, returns true.
So if getContext gives you a "falsey" value, the !! will make it return the boolean value false. Otherwise it will return true.
The "falsey" values are:
false
NaN
undefined
null
"" (empty string)
0
Javascript has a confusing set of rules for what is considered "true" and "false" when placed in a context where a Boolean is expected. But the logical-NOT operator, !, always produces a proper Boolean value (one of the constants true and false). By chaining two of them, the idiom !!expression produces a proper Boolean with the same truthiness as the original expression.
Why would you bother? Because it makes functions like the one you show more predictable. If it didn't have the double negative in there, it might return undefined, a Function object, or something not entirely unlike a Function object. If the caller of this function does something weird with the return value, the overall code might misbehave ("weird" here means "anything but an operation that enforces Boolean context"). The double-negative idiom prevents this.
In javascript, using the "bang" operator (!) will return true if the given value is true, 1, not null, etc. It will return false if the value is undefined, null, 0, or an empty string.
So the bang operator will always return a boolean value, but it will represent the opposite value of what you began with. If you take the result of that operation and "bang" it again, you can reverse it again, but still end up with a boolean (and not undefined, null, etc).
Using the bang twice will take a value that could have been undefined, null, etc, and make it just plain false. It will take a value that could have been 1, "true", etc. and make it just plain true.
The code could have been written:
var context = document.createElement('canvas').getContext;
var contextDoesNotExist = !context;
var contextExists = !contextDoesNotExist;
return contextExists;
Using !!variable gives you a guarantee of typecast to boolean.
To give you a simple example:
"" == false (is true)
"" === false (is false)
!!"" == false (is true)
!!"" === false (is true)
But it doesn't make sense to use if you are doing something like:
var a = ""; // or a = null; or a = undefined ...
if(!!a){
...
The if will cast it to boolean so there is no need to make the implicit double negative cast.
! casts "something"/"anything" to a boolean.
!! gives the original boolean value back (and guarantees the expression is a boolean now, regardless to what is was before)
The first ! coerces the variable to a boolean type and inverts it. The second ! inverts it again (giving you the original (correct) boolean value for whatever you are checking).
For clarity you would be better off using
return Boolean(....);
document.createElement('canvas').getContext may evaluate to either undefined or an object reference. !undefined yields true, ![some_object] yields false. This is almost what we need, just inverted. So !! serves to convert undefined to false and an object reference to true.
It's to do with JavaScript's weak typing. document.createElement('canvas').getContext is a function object. By prepending a single ! it evaluates it as a boolean expression and flips the answer around. By prepending another !, it flips the answer back. The end result is that the function evaluates it as a boolean expression, but returns an actual boolean result rather than the function object itself. Prepending !! is a quick and dirty way to typecast an expression to a boolean type.
If document.createElement('canvas').getContext isn't undefined or null, it will return true. Otherwise it will return false.

When to use the double not (!!) operator in JavaScript

I understand what the double not operator does in JavaScript. I'm curious about it's use though and whether or not a recent assertion that I made is correct.
I said that if (!!someVar) is never meaningful nor is (!!someVar && ... because both the if and the && will cause someVar to be evaluated as a boolean so the !! is superfluous.
In fact, the only time that I could think of that it would be legitimate to use the double not operator is if you wanted to do a strict comparison to another boolean value (so maybe in return value that expects true or false explicitly).
Is this correct? I started to doubt myself when I noticed jQuery 1.3.2 used both if (!!someVar) and return !!someVar && ...
Does the double not have any actual effect in these situations?
My personal opinion is that it just leads to confusion. If I see an if statement, I know it's evaluating it as a boolean.
In the context of if statements I'm with you, it is completely safe because internally, the ToBoolean operation will be executed on the condition expression (see Step 3 on the spec).
But if you want to, lets say, return a boolean value from a function, you should ensure that the result will be actually boolean, for example:
function isFoo () {
return 0 && true;
}
console.log(isFoo()); // will show zero
typeof isFoo() == "number";
In conclusion, the Boolean Logical Operators can return an operand, and not a Boolean result necessarily:
The Logical AND operator (&&), will return the value of the second operand if the first is truly:
true && "foo"; // "foo"
And it will return the value of the first operand if it is by itself falsy:
NaN && "anything"; // NaN
0 && "anything"; // 0
On the other hand, the Logical OR operator (||) will return the value of the second operand, if the first one is falsy:
false || "bar"; // "bar"
And it will return the value of the first operand if it is by itself non-falsy:
"foo" || "anything"; // "foo"
Maybe it's worth mentioning that the falsy values are: null, undefined, NaN, 0, zero-length string, and of course false.
Anything else (that is not falsy, a Boolean object or a Boolean value), evaluated in boolean context, will return true.
Yes, !!var is used when you want 0||1 return value.
One is simple comparison of bool values, when you want "a == b" be equivalent of "a xor not b" except a=5 and b=7 would both be true but not be equal.
Another is when you want to coerce a set of conditions into bits of a variable:
var BIT_NONEMPTY=1;
var BIT_HASERRORS=2;
var BIT_HASCHILDREN=4;
var BIT_HASCONTENT=8;
result_bitfields =
(!!countLines())*BIT_NOTEMPTY +
(!!errorCode())*BIT_HASERRORS +
(!!firstChild())*BIT_HASCHILDREN +
(!!getContent())*BIT_HASCONTENT;
Not very useful in Javascript which lives pretty far from bit values, but may be useful at times.

Categories