A javascript statement that I haven't seen before - javascript

I am inspecting some Javascript code written in UnderscoreJS. In this, there are quite a few instances of JS code being written like this:
if(length === +length){ //do something}
or
if(length !== +length){ //do something }
What exactly does this compute to? I have never seen this before.

if (length === +length)
It makes sure that the length is actually a numeric value.
Two things to understand here,
The Strict equality operator, will evaluate to true only when the objects are the same. In JavaScript, the numbers and strings are immutables. So, when you compare two numbers, the Number values will be compared.
Unary + operator will try to get the numeric value of any object. If the object is already of type Number, it will not make any changes and return the object as it is.
In this case, if length is actually a number in string format, lets say "1", the expression
"1" == +"1"
will evaluate to be true, because "1" is coerced to numeric 1 internally and compared. But
"1" === +"1"
which will be transformed to
"1" === 1
and that will not undergo coercion and since the types are different, === will evaluate to false. And if length is of any other type, === will straight away return false, as the right hand side is a number.
You can think of this check as a shorthand version of this
if (Object.prototype.toString.call(length) === "[object Number]")

It is a way of testing whether a value is numeric. See this for example:
> length="string"
> length === +length
false
> length=2
> length === +length
true
The unary + converts the variable length to the Number type, so if it was already numeric then the identity will be satisfied.
The use of the identity operator === rather than the equality operator == is important here, as it does a strict comparison of both the value and the type of the operands.
Perhaps a more explicit (but slightly longer to write) way of performing the same test would be to use:
typeof length === "number"

Related

Why is 1 == '1\n' true in Javascript?

The same goes for '1\t' (and probably others).
if (1 == '1\n') {
console.log('Equal');
}
else {
console.log('Not Equal');
}
As said before if you compare number == string, it will automatically try to convert the string to a number. the \n and \t are simply whitespace characters and therefore ignored.
This and similar behaviour can be rather confusing leading to situations like this:
(Picture taken from: https://www.reddit.com/r/ProgrammerHumor/comments/3imr8q/javascript/)
The equality operator(==) converts the operands if they are not of the same type, then applies strict comparison. If both operands are objects, then JavaScript compares internal references which are equal when operands refer to the same object in memory.
1 is of type Number hence '1\n' is converted to Number first then comparison takes place!
And Number() constructor will convert the string('1\n') to 1 :-
Number('1\n') === 1
In Strict equality using ===, Neither value is implicitly converted to some other value before being compared. If the values have different types, the values are considered unequal.
Hence 1 === '1\n' will be expressed as false

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

What's wrong with if (json.RowKey != json.NewRowKey)

I am using lint and for the following:
if (json.RowKey != json.NewRowKey)
It gives me a message:
Expected '!==' and instead saw '!='.
Can someone explain what this means?
== will attempt to convert the types of the two operands to be the same before comparing them. Thus "2" == 2 is true.
=== will not attempt to convert the types of the two operands so if they are not the same type, they will never be ===. Thus "2" === 2 is false.
It is better to use === and !== as your default choice and only use == or != when you explicitly want to allow type conversion. If you are not expecting the two operands to be different types, then === and !== is more likely to do what you are expecting.
This avoids coding mistakes when things are not really equal and your code doesn't intend for them to be equal.
Some odd things that happen with == (and do not happen with ===) that you may not expect and can lead to trouble. All of these evaluate to true:
null == undefined
false == '0'
0 == '0'
0 == ''
There's more detail written here: Which equals operator (== vs ===) should be used in JavaScript comparisons?
!== is not equal (neither value or type)
Eg:
var x = 5; x !== "5" returns true
var x = 5; x !== 5 returns false
It's a warning that tells you that you should consider using the !== operator instead of !=.
On the surface they both do the same thing - compare whether the two items are not equal. However, !== makes sure that both items are of the same type first (that is, it won't try to convert, say, a string to a number if one item being compared is a string and the other is a number), so it's generally safer to use and helps you avoid comparison errors.
For more details, see here: Which equals operator (== vs ===) should be used in JavaScript comparisons?
Yes,
if("1" == 1) //Returns true because it will convert the second 1 into a string to match
but
"1" !== 1 //Returns false because the first 1 is a string and the second 1 is an integer.
We are talking about variable types; with two equal signs, javascript (and php) will typecast the variable for you (convert the integer 1 into a string 1 to make the match and be true), but with the second statement, it will not.
1 === 1 //True
1 === "1" //False
1 == "1" //True
1 == 1 //True
Hope my answer makes sense to you.

Javascript equality triple equals but what about greater than and less than?

I was explaining to a colleague that you should use === and !== (and >== and <== of course) when comparing variables in JavaScript so that it doesn't coerce the arguments and get all froopy and confusing but they asked me a two part question that I did not know the answer to and thought I would ask the experts here, specifically it is:
What about > and < - when they compare do they also coerce the arguments or not - why isn't there some sort of >> and << operator (probably need to be some other syntax as I would guess they would be bit shift operators if it is going along the whole C style but you get the gist)?
So I can write a test to find the answer to the first part, which I did, here it is:
// Demo the difference between == and ===
alert(5 == "5");
alert(5 === "5");
// Check out what happens with >
alert(5 > "4");
alert(5 > 4);
and it returned:
true
false
true
true
so it does look like the > is doing the coercion since > "4" and > 4 return the same result. so how about the second part...
Is there some sort of operator for > and < that do not coerce the type (or how can I change my test to perform the test safely)?
No, there's no need for such operators. The type checking done for those relational operators is different than for equality and inequality. (edit — perhaps it's a little strong to say that there's "no need"; that's true only because JavaScript deems it so :-)
Specifically, the > and < and >= and <= operators all operate either on two numeric values, or two strings, preferring numeric values. That is, if one value is a number, then the other is treated as a number. If a non-number can't be cleanly converted to a number (that is, if it ends up as NaN), then the result of the comparison is undefined. (That's a little problematic, because undefined will look like false in the context of an if statement.)
If both values are strings, then a collating-order string comparison is performed instead.
If you think about it, these comparisons don't make any sense for object instances; what does it mean for an object to be "greater than" another? I suppose, perhaps, that this means that if you're finding yourself with values of variant types being compared like this, and that's causing problems, then yes you have to detect the situation yourself. It seems to me that it would be good to work upstream and think about whether there's something fishy about the code that's leading to such a situation.
Is there some sort of operator for > and < that do not coerce the type
No.
how can I change my test to perform the test safely
You would have to explicitly test the types:
typeof a === typeof b && a > b
I referenced Flanagan's JavaScript: The Definitive Guide (5th Ed.) and there does not seem to be non-coercive comparison operators.
You are right in saying the << and >> are indeed bitwise operators so that wouldn't work.
I would suggest you deliberately coerce the values youself:
var num_as_string = '4';
var num = +num_as_string;
if (5 > num) { ... }
12 > '100' // false
'12' > 100 // false
'12' > '100' // true
As others mentioned, if one is a number the other is casted to a number. Same rule applies to these cases as well:
null > 0 // false
null < 0 // false
null >= 0 // true
However, there might be cases that you would need null >= 0 to give false (or any of the number string comparison cases above), therefore it is indeed a need to have strict comparison >== or <==.
For example, I am writing a compareFunction for the Array.prototype.sort() and an expression like x>=0 would treat null values like 0's and put them together, whereas I want to put them elsewhere. I have to write extra logic for those cases.
Javascript says deal with it on your own (in practice).

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