Java is a Strong Static Casting so does that mean there is no use for "==="
I have looked at tons of documentation and have not seen Identical Comparison Operator.
=== is useful in weak typed languages, such as Javascript, because it verifies that the objects being compared are of the same type and avoids implicit conversions.
=== has absolutely no use in a strongly typed language such as Java because you can't compare variables of different types without writing a specific method for doing this.
For example, if you want to compare an int to a String in Java, you will have to write some special method as such:
boolean compareIntString(int i, String s) {
return (i == parseInt(s));
}
But this is pretty much overkill. (And as you'll notice, as written, this method only accepts an int and a String. It doesn't accept just any two variables. You know before you call it that the datatypes are different.)
The main point is, that while you can do i == s in Javascript, you can't do i == s in Java, so you don't need ===.
I guess, the short answer is that Java's == is Javascript's ===. If you want to emulate Javascript's == and compare two items, ignoring data type, you'll have to write a custom method which accepts generic data types as arguments... and figure out the logic on comparing, at a minimum, all the possible combinations of Java's primitive data types...
No java does not have === operator. Reason is pretty well explained by nhgrif. Here is the list of operators in java and their precedence:
Source: http://docs.oracle.com/javase/tutorial/java/nutsandbolts/operators.html
Related
While reading Intl.NumberFormat.prototype.format, I found out that the function can format a numeric string. However, in its syntax docs, only Number and BigInt are listed as valid argument types.
My question: Is this applies to every JS functions accepting a Number object?
A lot of built-in objects, methods, and functions are pretty loose with their types. Often, if you pass a type that isn't, strictly speaking, sensible to use with the method, the engine will attempt to coerce it for you. That's what's happening here too.
The behavior is specified:
When a Number format function F is called with optional argument value, the following steps are taken:
...
Let x be ? ToNumeric(value).
Return ? FormatNumeric(nf, x).
Can you always rely on this sort of coercion in general? No - but many things have been designed so that they work even with sloppy code, especially built-ins.
Code written in JavaScript (and not in the engine's underlying implementation) is, in general, significantly less likely to be tolerant of type problems. For example
const hasSubstring = (str, sub) => str.includes(sub)
will throw an error when called with a number, because Number.prototype.includes doesn't exist.
In JavaScript, it's commonly seen as best practice to use === instead of ==, for obvious and well-known reasons.
In TypeScript, which is one to be preferred? Is there even one which is preferable to the other one?
IMHO, using === in TypeScript doesn't make sense, since comparison already only works on equal types, hence you won't have the (more or less funny) coercion game as in plain JavaScript. If you take aside compatibility to JavaScript for a minute, TypeScript could even get rid of ===, couldn't it?
short version:
== can do unexpected type conversions, in Javascript 1=="1" is true. The === operator avoids this. Comparing different types with === is always false.
The typescript compiler will emit an error message when you compare different types with ==. This removes the unexpected type conversions that can happen with == in Javascript.
This is a case where valid Javascript leads to an error message in the typescript compiler. The idea that all valid Javascript is also valid Typescript is a common misconception. This is simply not true.
longer version:
I think the accepted answer is misleading. Typescript actually does fix == vs === (as far as possible at least).
In Javascript there are two comparison operators:
== : When comparing primitive values, like numbers and strings, this operator will apply a type conversion before doing the comparison. 1 == "1" evaluates to true.
===: This operator does not do type conversions. If the types don't match it will always return false.
Also, both operators will compare reference types based on their references. Two separate objects are never considered equal to each other, even if they store the same values:
let a = {val:1};
let b = {val:1};
c = a;
a==b; // false
a===b; // false
a==c; //true
a===c; //true
So there you have the two common sources of errors in Javascript comparisons:
comparing different types with == can lead to unexpected type conversions.
comparing objects and arrays is based on references not values stored inside.
As the existing answer already says, Typescript is designed as a superset of Javascript. So it doesn't change the behaviour of these comparison operators. If you write == in Typescript, you get type conversions.
So how is this fixed? With the compiler. If you actually do write code that compares incompatible types with == it's a compiler error. Try compiling the following sample:
let str = "1";
let num = 1;
console.log(str == num);
The compiler will tell you:
comparisons.ts:4:13 - error TS2367: This condition will always return 'false' since the types 'string' and 'number' have no overlap.
4 console.log(str == num);
~~~~~~~~~~
Found 1 error.
It is a common misconception that any valid Javascript is also valid Typescript. This is not true and the code above is an example where the typescript compiler will complain about valid Javascript.
This fixes the first of the two sources of errors: unexpected type conversions. It doesn't deal with the second source of errors: comparisons based on references. As far as I know, when you want to do a comparison based on values stored by the objects, you simply can't use these operators. You'll have to implement your own equals() method.
Also, you may have noticed that the compiler error is wrong. The comparison will not always evaluate to false. I think this is a bug in typescript and have filed an issue.
Imagine you're designing TypeScript from scratch. Essentially, you're trying to optimize for making safer code easier to write (TypeScript design goal 1) with a few caveats which prevent you from doing everything you'd like.
JavaScript compatibility (TypeScript design goal 7)
JavaScript should be valid Typescript with no changes.
CoffeeScript makes no guarantees regarding this, so it can convert all instances of == to === and simply tell users don't rely on =='s behavior. TypeScript cannot redefine == without breaking all JavaScript code that relies on its behavior (despite this having sad implications for 3).
This also implies that TypeScript cannot change the functionality of === to, for example, check the types of both operands at compile time and reject programs comparing variables of different types.
Further, compatibility is not limited to simply JavaScript programs; breaking compatibility also affects JavaScript programmers by breaking their assumptions about the differences between == and ===. See TypeScript non-goal number 7:
Introduce behaviour that is likely to surprise users. Instead have due consideration for patterns adopted by other commonly-used languages.
JavaScript as the target of compilation (TypeScript design goal 4)
All TypeScript must be representable in JavaScript. Further, it should be idiomatic JavaScript where possible.
Really though, the TypeScript compiler could use methods returning booleans for all comparisons, doing away with == and === entirely. This might even be safer for users: define a type-safe equality method on each TypeScript type (rather like C++ operator==, just without overloading).
So there is a workaround (for users comparing classes). unknown or any variables can have their types narrowed before using the type-safe equality method.
Which to prefer
Use === everywhere you would in JavaScript. This has the advantage of avoiding the pitfalls common to ==, and doesn't require you to maintain an additional method. The output of the TypeScript compiler will be close to idiomatic JavaScript. Using == has very much the same pitfalls as JavaScript, particularly when you have any, [], or {} involved. As an exception, using == null to check for null or undefined may save headaches if library code is inconsistent.
A method for reference equality (behavior like === for classes) could be confused with a deep/value recursive equality check. Furthermore, === is widely used in TypeScript, and making your code fall in line with conventions is usually more important than any small bit of type safety.
Your intuition was correct. There's no sense to use === in TypeScript to imitate an equality check. The argument that TS compiles to JS "so you should use what is better in JS" is not valid. Why? Because Typescript ensures that both operands of comparison operator(s) have the same type. When both operands have the same type == and === behave identically. And by "identically" I mean 100% identical not just "alike". So there's no more correct or less correct version when both behave exactly the same way in JavaScript.
I guess other commenters here are just looking for ways to preserve their habit of using === or in other words to rationalize. Unfortunately, pure logic tells otherwise: there's no sense to replace == with ===, unless you're going to modify generated JS code manually which is probably never the case.
I use === exclusively for identity checks (when you compare x to x – the same variables, it's sometimes necessary in library code related to memoization). And my counter of errors related to eqeq operator shows 0.
Example:
const s : string = "s"
const n : number = 1
console.log(s == n)
TS2367: This condition will always return 'false' since the types 'string'
and 'number' have no overlap
My opinion is that one should always use ===.
First line of reasoning: TypeScript does not change == to ===. There're TypeScript translators which just strip types. So using === everywhere leads to more robust code if for some reason you forgot to type check your program or if you (or future maintainer of your code) used type casts to override type safety. Should not happen but many things should not happen.
Second line of reasoning: null == undefined. This is true with TypeScript as well. I think that if one writes if (x == null) it makes code less readable because it implies check for undefined as well and implicit code is less readable than explicit if (x === null || x === undefined). Also subtle bugs might occur if this is not done on purpose.
I don't see any issues when just using === everywhere unconditionally other than aesthetic preferences.
Does OO JS have a mechanism for casting instance objects to boolean? I would like to be able to use custom instance objects directly in conditionals, and make assertions along the lines of !!(new Foo(0)) === false, !!(new Foo(1)) === true.
Python has __nonzero__ and __len__ (see here)
Ruby has to_bool.
How does JS do this for String literals "" and zero 0?
No, JS does not provide a trap method for casting to boolean. Truthiness of a value is statically determined by the language rules and cannot be changed.
You should give your instances a method to be explicitly invoked like isValid(), isTruthy(), isEmpty() or whatever concept your object represents.
I've been around the block when it comes to languages, having worked with everything from C# to Lisp to Scala to Haskell, and in every language that supported them, symbols have acted pretty much the same; that is, any two symbols with the same name, are guaranteed to be identical because they're singleton objects.
Racket: (equal? 'foo 'foo) true
Common Lisp: (eq 'foo 'foo) true
Ruby: :foo == :foo true
Scala: 'foo == 'foo true
ES6: Symbol('foo') === Symbol('foo') false
The benefit of symbols being singletons is obvious: You can use them in maps/dictionaries without risking your key not being equal to your input because the language suddenly decided to hash it differently (looking at you, Ruby)
So why is it that ECMAScript 6 takes a different approach on this, and how can I get around it?
You can (sort-of) get the effect of symbols being "knowable" by name by using registered (global) symbols:
var s1 = Symbol.for("foo");
var s2 = Symbol.for("foo");
s1 === s2; // true
Of course you can create your own Symbol registry too, with a Map instance or a plain object.
edit — I'll add that the intention of the optional string parameter when making a new Symbol instance is to provide a way of identifying the meaning and purpose of a symbol to the programmer. Without that string, a Symbol works just fine as a Symbol, but if you dump out an object in a debugger the properties keyed by such anonymous Symbol instances are just values. If you're keeping numeric properties on an object with Symbol keys, then you'll just see some numbers, and that would be confusing. The description string associated with a Symbol instances gives the programmer reference information without compromising the uniqueness of the Symbol as a key value.
Finally, you can always compare the result of calling .toString() on two similarly-constructed Symbol instances. I suspect that that practice would be considered questionable, but you can certainly do it.
edit more — it occurs to me that the fact that the default behavior of Symbol creation in JavaScript makes the type more useful than, say, atoms in Erlang or keys in Clojure. Because the language provides by default a value guaranteed to be unique, the fundamental problem of namespace collision is solved pretty nicely. It's still possible to work with "well-known" symbols, but having unique values available without having to worry about conflicts with other code that might also want to avoid collisions is nice. JavaScript has the somewhat unique, and certainly uniquely pervasive and uncontrollable, problem of a global namespace that may be polluted by code that a programmer does not even know exists, because code can collide in the browser enviroment due to the actions of a party different from, and unknown to, an arbitrary number of software architects.
This question already has answers here:
What's the reason to use === instead of == with typeof in Javascript?
(5 answers)
Closed 8 years ago.
In many examples of code I do see people using === when typechecking with typeof.
But typeof always returns a string. No matter which variable you are checking. So why typechecking this by using ===?
Example:
if(typeof num === 'number')
// do something
Is there any edge-case I dont know?
The typeof operator always returns a string, so the behavior will be identical. If you don't specifically need coercion, it's good practice to use the strictest available operator.
There shouldn't be a performance difference in this case, as typeof is guaranteed to return a string, so no coercion should ever be done. If someone changes the code, however, using === will force the new code to also return a string (or make them update the condition).
The == operator is useful when you need to compare two values of different (or potentially different) types, but if you know ahead of time the types will be identical, === has all the benefits and enforces strict comparison. Later on, if someone wants to make the code less strict, they have to explicitly do so.
=== is usually faster than ==.
If you compare two values while ignoring their their type (==), javascript usually has to convert one or both of the values to another type internally and do additional checks.
=== on the other hand does not have to convert anything and only has to do one comparison. So when you do not have to worry about cases like "1" == 1, === is usually faster.
In this case, as typeof always returns a string and the second value also is a string, == is not needed, so === is uses out of convention.
If there is no type conversion possible in a given comparison (which there is not with typeof x === "string" because typeof always returns a string), then there is no functional difference between == and ===. Which to use in that case is more a matter of preferred style since there is no functional difference.
So, in your case of:
if (typeof num === 'number')
there is no functional difference between that and the == version:
if (typeof num == 'number')
Either will provide the exact same result no matter what value num has. You can use either version and your code will run correctly in all cases.
Is there any edge-case I dont know?
No, there are no edge cases for this particular example.
So why typechecking this by using ===?
One popular recommendation for Javascript coding is to always use === unless you explicitly WANT a type conversion to be allowed. This is considered a safer coding style because you won't accidentally get a type conversion that you weren't thinking about or planning for.
So, if you are following this recommendation, then you get yourself in a frame of mind that your default coding style is to use === unless there is a reason NOT to use it (e.g. you want a type conversion to be allowed).
That is the opposite of your logic where you are looking for a reason to use === instead of looking for a reason not to use ==.