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.
Related
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"
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).
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Implied string comparison, 0='', but 1='1'
Executing the following case in javascript, I get 0 equal to '' (an empty string)
var a = 0;
var b = '';//empty string
if(a==b){
console.log('equal');//this is printed in console
}else{
console.log('not equal');
}
Could anyone guide that what is the reason behind this?
Quoting the doc (MDN):
Equal (==)
If the two operands are not of the same type, JavaScript converts the
operands then applies strict comparison. If either operand is a number
or a boolean, the operands are converted to numbers if possible; else
if either operand is a string, the other operand is converted to a
string if possible.
As a operand type here is Number, b gets converted to Number as well. And Number('') evaluates to 0.
This can be quite surprising sometimes. Consider this, for example:
console.log(0 == '0'); // true
console.log(0 == ''); // true
console.log('' == '0'); // O'RLY?
... or this:
console.log(false == undefined); // false
console.log(false == null); // false
console.log(null == undefined); // fal.... NO WAIT!
...and that's exactly why it's almost always recommended to use === (strict equality) operator instead.
0, "" (Empty String), false all technically have the same value, when typecasted. If you need to strictly treat them, you can use ===.
It is the same with similar programming languages, like PHP.
var a = 0;
var b = ''; //empty string
if(a == b){
console.log('equal'); //this is printed in console
}else{
console.log('not equal');
}
To make a strict comparison:
if(a === b){
console.log('equal');
}else{
console.log('not equal'); //this is printed in console
}
== operator in javascript don't compare types so 0=='' === true (because as a number string '' evaluates to 0) or 0==false === true (because bool false evaluates to 0) to compare types to you can use === operator.
Here you'll find useful information about comparison.
Javascript automatically converts variables of different types for comparison. That's a common feature in non-strictly typed languages.
If you need to compare variables and check the type, use the === operator.
In most programming language(including javascript) ""(string), 0(integer), \x0(null) losely mean the same thing: "empty". What's happening is your javascript engine finds "" == 0 false, due to the == it converts 0 to an integer. Again this is false, so it converts 0 to null which is false, so then it converts 0 to an empty string. (Not sure if this is the correct order of conversion). To make the condition "exact" match(no conversion) use === inplace of ==
== does typecasting. Always use ===.
In your example, the empty string of b is being converted to 0. So both a and b are the same.
Because empty string represented as number is zero. If you compare apples and oranges you should think of how your particular orange would look if it were an apple.
Because of coercion. It is usually a better idea to use === for comparisons in JavaScript.
Because == checks value equality so false, 0 and empty strings are equals. Use identity check ===.
The following shows that "0" is false in Javascript:
>>> "0" == false
true
>>> false == "0"
true
So why does the following print "ha"?
>>> if ("0") console.log("ha")
ha
Tables displaying the issue:
and ==
Moral of the story use ===
table generation credit: https://github.com/dorey/JavaScript-Equality-Table
The reason is because when you explicitly do "0" == false, both sides are being converted to numbers, and then the comparison is performed.
When you do: if ("0") console.log("ha"), the string value is being tested. Any non-empty string is true, while an empty string is false.
Equal (==)
If the two operands are not of the same type, JavaScript converts the operands then applies strict comparison. If either operand is a number or a boolean, the operands are converted to numbers if possible; else if either operand is a string, the other operand is converted to a string if possible. If both operands are objects, then JavaScript compares internal references which are equal when operands refer to the same object in memory.
(From Comparison Operators in Mozilla Developer Network)
It's according to spec.
12.5 The if Statement
.....
2. If ToBoolean(GetValue(exprRef)) is true, then
a. Return the result of evaluating the first Statement.
3. Else,
....
ToBoolean, according to the spec, is
The abstract operation ToBoolean converts its argument to a value of type Boolean according to Table 11:
And that table says this about strings:
The result is false if the argument is the empty String (its length is zero);
otherwise the result is true
Now, to explain why "0" == false you should read the equality operator, which states it gets its value from the abstract operation GetValue(lref) matches the same for the right-side.
Which describes this relevant part as:
if IsPropertyReference(V), then
a. If HasPrimitiveBase(V) is false, then let get be the [[Get]] internal method of base, otherwise let get
be the special [[Get]] internal method defined below.
b. Return the result of calling the get internal method using base as its this value, and passing
GetReferencedName(V) for the argument
Or in other words, a string has a primitive base, which calls back the internal get method and ends up looking false.
If you want to evaluate things using the GetValue operation use ==, if you want to evaluate using the ToBoolean, use === (also known as the "strict" equality operator)
It's PHP where the string "0" is falsy (false-when-used-in-boolean-context). In JavaScript, all non-empty strings are truthy.
The trick is that == against a boolean doesn't evaluate in a boolean context, it converts to number, and in the case of strings that's done by parsing as decimal. So you get Number 0 instead of the truthiness boolean true.
This is a really poor bit of language design and it's one of the reasons we try not to use the unfortunate == operator. Use === instead.
// I usually do this:
x = "0" ;
if (!!+x) console.log('I am true');
else console.log('I am false');
// Essentially converting string to integer and then boolean.
Your quotes around the 0 make it a string, which is evaluated as true.
Remove the quotes and it should work.
if (0) console.log("ha")
It is all because of the ECMA specs ... "0" == false because of the rules specified here http://ecma262-5.com/ELS5_HTML.htm#Section_11.9.3 ...And if ('0') evaluates to true because of the rules specified here http://ecma262-5.com/ELS5_HTML.htm#Section_12.5
== Equality operator evaluates the arguments after converting them to numbers.
So string zero "0" is converted to Number data type and boolean false is converted to Number 0.
So
"0" == false // true
Same applies to `
false == "0" //true
=== Strict equality check evaluates the arguments with the original data type
"0" === false // false, because "0" is a string and false is boolean
Same applies to
false === "0" // false
In
if("0") console.log("ha");
The String "0" is not comparing with any arguments, and string is a true value until or unless it is compared with any arguments.
It is exactly like
if(true) console.log("ha");
But
if (0) console.log("ha"); // empty console line, because 0 is false
`
This is because JavaScript uses type coercion in Boolean contexts and your code
if ("0")
will be coerced to true in boolean contexts.
There are other truthy values in Javascript which will be coerced to true in boolean contexts, and thus execute the if block are:-
if (true)
if ({})
if ([])
if (42)
if ("0")
if ("false")
if (new Date())
if (-42)
if (12n)
if (3.14)
if (-3.14)
if (Infinity)
if (-Infinity)
This is the reason why you should whenever possible use strict equality === or strict inequality !==
"100" == 100
true because this only checks value, not the data type
"100" === 100
false this checks value and data type
The "if" expression tests for truthiness, while the double-equal tests for type-independent equivalency. A string is always truthy, as others here have pointed out. If the double-equal were testing both of its operands for truthiness and then comparing the results, then you'd get the outcome you were intuitively assuming, i.e. ("0" == true) === true. As Doug Crockford says in his excellent JavaScript: the Good Parts, "the rules by which [== coerces the types of its operands] are complicated and unmemorable.... The lack of transitivity is alarming." It suffices to say that one of the operands is type-coerced to match the other, and that "0" ends up being interpreted as a numeric zero, which is in turn equivalent to false when coerced to boolean (or false is equivalent to zero when coerced to a number).
if (x)
coerces x using JavaScript's internal toBoolean (http://es5.github.com/#x9.2)
x == false
coerces both sides using internal toNumber coercion (http://es5.github.com/#x9.3) or toPrimitive for objects (http://es5.github.com/#x9.1)
For full details see http://javascriptweblog.wordpress.com/2011/02/07/truth-equality-and-javascript/
I have same issue, I found a working solution as below:
The reason is
if (0) means false, if (-1, or any other number than 0) means true. following value are not truthy, null, undefined, 0, ""empty string, false, NaN
never use number type like id as
if (id) {}
for id type with possible value 0, we can not use if (id) {}, because if (0) will means false, invalid, which we want it means valid as true id number.
So for id type, we must use following:
if ((Id !== undefined) && (Id !== null) && (Id !== "")){
} else {
}
for other string type, we can use if (string) {}, because null, undefined, empty string all will evaluate at false, which is correct.
if (string_type_variable) { }
In JS "==" sign does not check the type of variable. Therefore, "0" = 0 = false (in JS 0 = false) and will return true in this case, but if you use "===" the result will be false.
When you use "if", it will be "false" in the following case:
[0, false, '', null, undefined, NaN] // null = undefined, 0 = false
So
if("0") = if( ("0" !== 0) && ("0" !== false) && ("0" !== "") && ("0" !== null) && ("0" !== undefined) && ("0" !== NaN) )
= if(true && true && true && true && true && true)
= if(true)
I came here from search looking for a solution to evaluating "0" as a boolean.
The technicalities are explained above so I won't go into it but I found a quick type cast solves it.
So if anyone else like me is looking to evaluate a string 1 or 0 as boolean much like PHP. Then you could do some of the above or you could use parseInt() like:
x = "0";
if(parseInt(x))
//false
I was debugging something and discovered some strangeness in JavaScript:
alert(1=='') ==> false
alert(0=='') ==> true
alert(-1=='') ==> false
It would make sense that an implied string comparison that 0 should = '0'. This is true for all non-zero values, but why not for zero?
According to the Mozilla documentation on Javascript Comparison Operators
If the two operands are not of the same type, JavaScript converts the
operands then applies strict
comparison. If either operand is a
number or a boolean, the operands are
converted to numbers; if either
operand is a string, the other one is
converted to a string
What's actually happening is that the strings are being converted to numbers.
For example:
1 == '1' becomes 1 == Number('1') becomes 1 == 1: true
Then try this one:
1 == '1.' becomes 1 == Number('1.') becomes 1 == 1: true
If they were becoming strings, then you'd get '1' == '1.', which would be false.
It just so happens that Number('') == 0, therefore 0 == '' is true
When javascript does implicit type conversions, the empty string literal will match the 0 integer. Do your comparison like this and you'll get your expected result:
alert(1==='') ==> false
alert(0==='') ==> false
alert(-1==='') ==> false
ECMA-262, 3rd edition, 11.9.3 regarding x == y, step 16:
If Type(x) is Number and Type(y) is String, return the result of the comparison x == ToNumber(y).
The empty string '' gets converted to 0 before the comparison.
This is just one of the truly hideous mangles that went into the JavaScript compromise. '' and 0 are both uninitialized values (equal to boolean false) and, therefore, equal.
To protect yourself from weird bugs like this, it's better to always use the === operator.
Javascript, like PHP, is weakly typed*. So when you compare 0 to '', the JS engine converts them to a similar datatype. Since 0 and '' both equate to boolean(false), "false == false" is true.
*Weakly typed languages do not require variables to be any specific data type, so you can set one variable as a string, change it to int, float, and back to string without the processor throwing errors.
In many languages, the empty string can be coerced to false.
Beware of doing comparisons with == instead of ===:
alert('' == '0'); //false
alert(0 == ''); // true
alert(0 =='0'); // true
== is not transitive.