Assignment operator inside if clause assigns value and performs check? - javascript

I noticed something whilst debugging my code.
if(array.length=5){
console.log("it's 5 units long");
}
This not only makes the array size 5(assuming it performs the assignment every time) but it also performs the check in the if, resulting in a console output. Is this normal behaviour in Javascript and is this a valid shorthand for any real scenario?

The result of an assignment expression is the new value. Your code is equivalent to:
array.length = 5;
if (5) {
console.log("it's 5 units long");
}
And 5 is a truthy value, so the condition passes.
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.
I can contrive scenarios where this would be useful, but generally, no, it's not useful. At the very least, it's bad style, and shouldn't be used even if it can be.

Related

php boolean's lower AND upper case and numerical boolean's acceptable?

I have this line of code in PHP:
if($connect->query("INSERT INTO users (last_login) VALUES ('$now')") === TRUE) ...
and this line.
return true;
I've noticed that PHP booleans are sometimes uppercase and sometimes lowercase.
Why is this?
Should I use one for better performance?
Do they produce different results?
If so, what is the difference?
Are numeric booleans acceptable in PHP, because in JavaScript, booleans can be 0 and 1.
IE in JavaScript, you can do:
if(0) ... // false
if(1) ... // true
You can assign a truth value manually by stating that with the identity operator =.
$var = TRUE; // or true, is the same.
Anyway, boolean values are assigned automatically according to the nature of the variable you are considering. For example, a numeric value will be FALSE if it is 0, or TRUE in the other cases. A string will be FALSE just if empty.
PHP's rules on type-looseness and boolean conversions are fairly complex. From the docs (and Damien's comment): To specify a boolean literal, use the constants TRUE or FALSE. Both are case-insensitive.
Further down the page, under the "Converting to boolean" heading, all of the rules of numeric booleans, string booleans, etc. I'd recommend familiarizing yourself with them to avoid unintentional behavior. To answer your question directly: yes, numeric booleans are supported. And empty strings. And the string "0" will also count as false.

How does JavaScript evaluate if statement expressions?

I always thought that JavaScript's if statements did some kind of casting magic to their arguments, but I'm a little wary of what's actually going on behind the scenes.
I recently found a JavaScript comparison table and noticed that even though -1 == true evaluates to false, if(-1){...} will execute.
So within JavaScripts if statements, what happens to the expression? It seems reasonable to assume that it uses !!{expression} to cast it to an inverse boolean, then invert it again, but if that's the case, how does JS decide whether an object's inverse boolean representation is truthy or not?
JavaScript is wonky.
Yes, -1 == true results in false, but that's not what the if statement is doing. It's checking to see if the statement is 'truthy', or converts to true. In JavaScript, that's the equivalent of !!-1, which does result in true (all numbers other than zero are truthy).
Why?!?
The spec defines the double equals operator to do the following when presented with a number and a boolean:
If Type(y) is Boolean, return the result of the comparison x == ToNumber(y).
ToNumber will convert the boolean true into the number 1, so you're comparing:
-1 == 1
which anyone can tell you is clearly false.
On the other hand, an if statement is calling ToBoolean, which considers any non-zero, non-NaN number to be true.
Any JavaScript developer really needs to look at the documentation -- for this case, located here: http://www.ecma-international.org/ecma-262/5.1/#sec-9.2
9.2 ToBoolean
The abstract operation ToBoolean converts its argument to a value of type Boolean according to Table 11:
Argument Type Result
Undefined false
Null false
Boolean The result equals the input argument (no conversion).
Number The result is false if the argument is +0, −0, or NaN; otherwise the result is true.
String The result is false if the argument is the empty String (its length is zero); otherwise the result is true.
Object true
(Sorry about the formatting, can't make a table here.)
From JavaScript The Definitive Guide
The following values convert to, and therefore work like, false:
undefined
null
0
-0
NaN
"" // the empty string
All other values, including all objects (and arrays) convert to, and work like, true. false, and the six values that convert to it, are sometimes called falsy values, and all other values are called truthy.
These things by themselves are falsy (or evaluate to false):
undefined
null
0
'' or ""
false
NaN
Everything else i truthy.
Truthy-ness or falsy-ness is used when evaluating a condition where the outcome is expected to be either truthy (true) or falsy (false).
In your example if(-1 == true), you are comparing apples and oranges. The compare is evaluated first (and resulted in false), and the results of that is used in your condition. The concept of truthyness/falsyness isn't applied to the operands the comparison.
When if state using with comparing variable different type js use .toString и .valueOf ( for more information check http://javascript.info/tutorial/object-conversion ) - just keep this in mind - it make so example much more easy to understand

Why eval("475957E-8905") == "475957E-8905" is true?

I made a program with nodeJs which generate code such as
eval("XXXXXX") == "XXXXXX"
It's working pretty well, but at a moment he gave me this :
eval("475957E-8905") == "475957E-8905"
I tested it with Firebug, and the result is true
.But I don't really understand why.
Of course, eval("475957E-8905") return 0
but why 0 == "475957E-8905" ?
There are two pieces to this puzzle: floating-point numbers and type-insensitive comparison using ==.
First, 475957E-8905 evaluates as the floating point number 475957 * 10 ^ -8905, which is incredibly small; in floating-point terms, it's the same as 0 due to the precision limitations of javascript. So, eval("475957E-8905") returns 0.
Now, for the second piece of the puzzle.
The == means that the types don't have to match, so nodejs (like any JavaScript engine) tries to convert one of them so it can compare them.
Since eval("475957E-8905") returned 0, it tries to convert "475957E-8905" to an integer as well. As we have seen, that is also 0. Thus, the comparison is 0 == 0, which is true.
Note that the same thing happens if you do eval("3") == "3" or eval("3") == 3 -- in each case, the strings are converted to numbers and compared.
Avoiding this problem
You can force a type-sensitive comparison like this:
eval("475957E-8905") === "475957E-8905"
which returns false, because the === tells the javascript engine to return true only if the types and the values both match.
Javascript has to convert your string, "475957E-8905", to a number in order to compare them. When it does that, it converts "475957E-8905" to 0 as well. So, 0 == 0;
As you can see:
"475957E-8905" == 0
Is true. Basically you eval statement "475957E-8905" into a number, and then the other "475957E-8905" is being converted to a number for comparison. In the end, the exact same conversion process has happened to both of them and they are both 0.
use === to compare the type as well, for further information:
JavaScript has both strict and
type-converting equality comparison.
For strict equality the objects being
compared must have the same type and:
Two strings are strictly equal when they have the same sequence of
characters, same length, and same
characters in corresponding positions.
Two numbers are strictly equal when they are numerically equal (have
the same number value). NaN is not
equal to anything, including NaN.
Positive and negative zeros are equal
to one another.
Two Boolean operands are strictly equal if both are true or
both are false.
Two objects are strictly equal if they refer to the same Object.
Null and Undefined types are == (but not ===). [I.e. Null==Undefined (but not Null===Undefined)]
check this documentation

why do both if('0'==false) and if('0') evaluate to true in Javascript?

So for what I know is that the if statement in Javascript casts the result of its condition to a Boolean, and then executes it likes the following
if(true) {
// run this
}
if(false) {
// do not run this
}
And that works. But If I do this:
if('0' == false) {
// We get here, so '0' is a falsy value
}
Then I would expect this
if('0') {
// We don't get here, because '0' is falsy value
}
But instead I get
if('0') {
// We *DO* get here, even though '0' is falsy value
}
So what's happening? Apparently, if does not check if its condition a truthy or falsy value, but does some other conversion?
This is just one of those "gotchas" with the == rules which are rather complex.
The comparison x == y, where x and y are values, produces true or false. Such a comparison is performed as follows:
(4) If Type(x) is Number and Type(y) is String,
return the result of the comparison x == ToNumber(y).
(5) If Type(x) is String and Type(y) is Number,
return the result of the comparison ToNumber(x) == y.
(6) If Type(x) is Boolean, return the result of the comparison ToNumber(x) == y.
(7) If Type(y) is Boolean, return the result of the comparison x == ToNumber(y).
In this case that means that '0' == false is first coerced do '0' == 0 (by rule #7) and then on the second pass through, it is coerced to 0 == 0 (by rule #5) which results in true.
This particular case is somewhat tricky because of false ~> 0 instead of '0' ~> true (as what might be expected). However, '0' is itself a truth-y value and the behavior can be explained with the above rules. To have strict truthy-falsey equality in the test (which is different than a strict-equality) without implicit conversions during the equality, consider:
!!'0' == !!false
(For all values: !falsey -> true and !truthy -> false.)
This:
if('0') {
// We *DO* get here, even though '0' is falsy value
}
checks to see if the string is null or empty, not whether it's zero or not. Any non-empty string is truthy.
When you do this:
if('0' == false) {
// We get here, so '0' is a falsy value
}
you are asking the JS engine for an explicit type conversion to try to match the type of the two operands. That is different than just asking if one operand is truthy all by itself.
In general, you will find that you get fewer unexpected results if you nearly always use === and !== and only allow type coercion when you know exactly what is going to happen in all cases either because you fully understand the very complex coercion rules or because you know what types will be present and you understand those specific cases.
if ('0' == false):
Javascript is doing something called type coercion.
Following the rules in that link, we fall to rule 7:
If Type(y) is Boolean, return the result of the comparison x == ToNumber(y)
Calling ToNumber(false) gives us a numeric 0. The result now starts to make sense, but we're still not quite done, because we still have a string and a number. The process starts again, and this time we fall to rule 5:
If Type(x) is String and Type(y) is Number, return the result of the comparison ToNumber(x) == y: "2" == 2
This time, the left side '0' is converted to a number: 0. Now, at last, we can compare two Numbers, and since 0 equals 0, the result is true. However, it's important to note that this implies nothing at all about the truish/falsy nature of the '0' string, because it was coerced before it was compared.
if('0')
In this case, there is no comparison; you only want to know if a single value is "truish" or "falsy". No type coercion is used, because strings can be evaluated as truish or falsy on their own merits. Using the rules at the same link as before, we find this information:
In JavaScript, and not only JavaScript, we have so called falsy values. These are respectively: 0, null, undefined, false, "", NaN. Please note the empty string is empty, 'cause differently from php as example, "0" will be considered truish
The quote is especially helpful because it specifically calls out the '0' string, but that would not be necessary. It's enough to know that an empty string is falsy, and any other string is truish, because the content of the string is not evaluated and no coercion is performed. 0 may be a falsy value, but because we evaluate a string rather than coercing to a number, and '0' has a value of some kind, it is still truish.
Javascript operator == does type conversion and is basically useless. Just avoid it.
For example:
[] is truty but [] == false is true
1 == "1", [1] == "1", [[1]] == "1" are all true
[1] == [[1]] however is false
The rules are VERY weird. For example in the first case [] gets converted to "" that gets converted to a number and the value is 0. false is also converted to the number 0. So in the end they compare equal.
Note however that while the conversion from the empty string to a number gives 0, the result of parseInt("") is NaN.
PS: The real fun is when you discover that [30,20,10,3,2,1].sort() returns [1,10,2,20,3,30] (yes... numbers, yes in lexicographical order). No I'm not kidding.

Javascript if-statement vs. comparsion

Is it true that in if-statement JavaScript wrap the condition into a Boolean?
if(x) => if(Boolean(x))
Is it true that in comparison JavaScript wrap the compare elements into a Number?
a == b => Number(a) == Number(b)
Yes, and No.
For the first part, yes, that is essentially what the javascript does.
But for the latter, no. Not everything in JavaScript can be converted to a number. For example:
Number('abc') // => NaN
And Not-A-Numbers are not equal:
NaN == NaN // => false
So something like this:
Number('abc') == Number('abc') // => false!
But that's actually true with equality comparison.
'abc' == 'abc' // => true
As a side note, it's probably better to use === in JavaScript, which also checks the type of the values being compared:
0 == '0' // => true
0 === '0' // => false, because integer is not a string
More details about === can be read over here.
Yes, that's true, x is evaluated in a boolean context in this situation, so the equivalent of Boolean(x) is applied.
No, that's not true. It only looks that way because the coercitive equality operator == tries to convert a and b to the same type. Number() is only applied if either a or b is already a Number. For instance:
>>> 0x2A == 42
true // both 'a' and 'b' are numbers.
>>> "0x2A" == 42
true // 'a' is a string whose number coercion is equal to 'b'.
>>> "0x2A" == "42"
false // 'a' and 'b' are different strings.
Is it true that in if-statement JavaScript wrap the condition into a Boolean?
Usually yes.
Is it true that in comparison JavaScript wrap the compare elements into a Number?
Absolutely no.
Explanation
From JavaScript Language Specifications.
The if statement is defined at § 12.5 as:
if ( Expression ) Statement else Statement
It says that the Expression will be evaluated, converted with GetValue() and then tested after the ToBoolean() conversion.
Then the first assertion is true (but see later), the condition for the if statement is evaluated like is passed as parameter to the Boolean function. Please recall how JavaScript handles type conversion to boolean (§ 9.2):
undefined and null values are converted to false.
numbers are converted to false if ±0 or NaN otherwise they're converted to true.
strings are converted to false if empty otherwise always to true regardless their content.
objects are always converted to true.
Because of the call to GetValue() strictly speaking this assertion is not always true, take a look to § 8.7.1 where the standard describes how GetValue() works, here can happen some magic conversion before ToBoolean() is called.
The == operator is defined as in § 11.9.3.
As you can see it doesn't specify that operands must be (or will be treated as) numbers, the behavior of the operator is different and regulated by a series of rules based on the type of the operands. Then your second assertion is false. The case they're numbers (or one of them is a number) is just a special case in the algorithm, please note that at point 4 of the algorithm it says that if one of them is a number and the other one is a string then it'll be converted with ToNumber(), only in this case (with all the implications that this conversion has).
It's intuitive if you think that you can compare functions, strings or numbers, not every type can be converted to a numeric value.

Categories

Resources