There is a followup article "Don't Make Javascript Equality Look Worse Than It Is"
"These posts are fundamentally right about == being poorly designed... but they make things look worse by failing to organize the table.... What a mess! But most of the mess is because of the order of values in the table. By grouping equal values together, you get something more sensible"
Do you often find that you have no idea whether your variable contains a string or a number? Either your data comes from user input, an API, or some file-like source. If it's user input, say from an <input>, you would already know to parseInt(). If it's from an API then presumably it's conforming to a documented spec. If it's from a file or something less than conformant, safely parse it.
Why/how would you get to the point where you're operating on the value without being certain of its type?
> Why/how would you get to the point where you're operating on the value without being certain of its type?
My favorite example of this is the twitter API, which used to report retweet count as the string "100+" for the case of over 100 retweets. This behavior was not documented [1], so until you encounter that example, you wouldn't necessarily expect this or defend against a string
How could === defend you in this case? `"100+" != 100` already.
If you do a typeof before further processing the value then you'll know how to treat it, and additionally someone who comes after you will realize that the value could be a number or a string.
Instead of using === everywhere, if you parse and cast your input to known types you also have the opportunity to catch errors where input is not conforming.
Your parsing makes it obvious to other programmers what your assumptions are about the input. With === all a person will see is that the expected condition did not trigger but no obvious reason why. If `key === 13` fails all we know is that there is no strict equality, but `parseInt(key) == 13` failing means that key is not something which could parse to number 13, and consequently what type(s) key can be is obvious.
Moreover with parseInt the left side of that operator will always be a number or NaN, and the right side is a scalar, so there is no justification for using `parseInt(key) === 13`. It would be preposterous. If you can't trust the return type of parseInt, then your programming environment is unreliable.
== vs. === aside, it's a bit hypocritical to use === because it's safer when you're using undefined as a keyword. You can't tell just from looking at that line whether the variable undefined is actually undefined or not; it could, in fact, be defined (below the global scope, that is -- unless you're in an older browser, I suppose).
Granted, defining a variable called undefined would be absurd, and I realize I'm nitpicking here, but if we're trying to make a point about good practice, typeof would be the way to go. (Of course, more often you only really care if something == null or not, so you'd just do a simple == null check, like you said.)
I hate seeing "==" in code because it's rarely clear whether the programmer intends it to coerce or just didn't bother with the third keystroke. So "===" is just enforced everywhere through jshint.
Might the === comparison be faster, since the underlying JavaScript engine doesn't need to determine how the two types should be cast back and forward to be compared?
Yes there is a reason, because somebody reading the code is going to have to wonder why the heck you used a double-equals, and the code could be edited later in such a way that the triple-equals becomes relevant again.
If Type(y) is Boolean, return the result of the comparison x == ToNumber(y).
So the boolean is coerced to a number, and new Number(true) => 1. I wonder why they didn't do it the other way around, and make the number a boolean like above. You're losing seemingly useful information with new Number(<boolean>)
`2` is truthy, but `==` forces a coercion, which ends up converting Boolean `true` to a number, which is 1 (`ToNumber(true) := 1` [1]), which is ostensibly not equal to 2.
I forget the specifics of Javascript, but in many languages "truthy" (used in ifs) is usually closer to "!= false" than "== true". e.g. any object or non-zero number is truthy (except "" in JS), but only a handful are actually == true or == false.
Most of these scenarios are mitigated by knowing what types of data are coming into your functions. If you're defending against a string being compared to a number, I'd sooner wonder why you don't know whether you have a string or a number in your variable in the first place. What could cause you to attempt to use `[1]`(array containing number 1 as an element) as a boolean? Seems like you should know if a variable contains an array and not true/false, and if you don't then that's a better place to focus your attention.
If my "number" is in fact a string I'd like to get an error instead of a type conversion that hides this error. This might not necessarily be an ignorant beginner mistake, but may very well be a manifestation of some complicated bug or error on the other end of the program, possibly in a library I haven't studied enough and made assumptions about, or a black-box webservice.
I can handle it but don't see why I would go out of my way to defend Javascript in this regard.
> If my "number" is in fact a string I'd like to get an error instead of a type conversion that hides this error.
If you expect a number or a string, call parseInt() on your value and then isNaN() on that will tell you whether you have an error condition. Your code will be more understandable if you spend time parsing your inpt and explicitly casting to expected types, rather than papering over differences with ===
Wrong jessedhillon, becaue parseInt() is as quirky as == (this is JavaScript, remember!).
parseInt('1 are you joking') returns 1.
parseInt('077') returns 63 on some older browsers (get off my octal lawn).
parseInt('0XALIC ACID') returns 10.
parseInt(' -1e5') returns -1.
And dealing with Integers in JavaScript is fraught with danger since browser JavaScript only really knows floating point numbers. e.g. parseInt('999999999999999999999999999999999999999999999999999999999999999999999999999999999') returns 1e+81...
Smoke that!
Edit: It is possible to build some reliable integer routines using logical operators (since they convert to unsigned integers to perform the operation) but one needs to understand the other underlying quirks to do so.
Yes, it's parseInt() plus some further checks if the results are within an expected range in my code. And overall being more verbose, explicit, and careful. And the occasional squinting eyes from the "Fry meme".
I see the problem - the empty string is in a different position between the rows and columns, leading to "" being equal to the string "True", which is false.
I am not sure what's up with the first two. But in the latter one, I believe the array is being coerced to a string, which is its contents separated by commas, so in this case just "42". Then either the left-hand 42 is coerced to a string or the right-hand "42" is coerced to a number, I'm honestly not sure. It hasn't been all that long since I read the spec about this, either. Sheesh.
That's actually pretty important: it means that == and != are commutative. Imagine the "wat" if that wasn't the case either. And hey, it's JS, it could've been.
This implies there is no equivalence relation with == in JS. In order to form an equivalence relation, it would need to be reflexive, symmetric and transitive.
Your conviction and intelligence definitely show from your decision to use a throwaway to reply!
Out of curiosity, what should people be using instead of Go? (And don't say Haskell, because surely you're more pragmatic than that.)
I'm looking at Elixir now, but Go has a growing community and great concurrency.
It seems to me that you perhaps hate any language that encourage or forces OO design, even though almost no one does real, widely-used, functional projects.
For real projects (ones that definitely involve other people and probably involve money in some way), most of your wasted time is not due to the language you're using.
Sure, you could be using non-strict JS or PHP and get bogged down because your typos are silently ignored, but lots of IDEs have static analysis and whatnot to prevent that. Any popular language has workarounds for its most time-wasting issues.
Where lots of time is actually lost is 1) learning and 2) reinventing the wheel.
Imagine, for example, that there's a magical language called AFP (Absolutely Fucking Perfect). It's perfect. Everything you write in it is short, concise, readable, maintainable, and compiles to hyper-efficient code for any number of cores.
Unfortunately, AFP is only used by 1,000 people. See the problem here? The time you spend learning is going to be astronomical, because you won't find the tutorials, Stack Overflow questions, books, forum posts, etc. that you find with a popular language.
And then, perhaps worse, you don't have many libraries. None of those other 1,000 people were working with REST APIs? That sucks, you have to write a module for that. None of them needed to process images? Same issue.
With AFP, you're likely looking at writing 10 times the amount of code that you would in a popular pile of garbage like PHP or JS.
Haskell is AFP. It's widely considered to be a great language, but it's just not practical. There's hardly anything built in Haskell out there for you to build your own stuff on.
We're now getting into an era where we might have the best of both worlds. Rust seems to be really interesting on that front. I've also seen the same argument for Scala, Go, and Elixir. But Haskell is not one of those frontrunner languages to take over from the slapped-together old guard of Perl, PHP, Python, and JS.
Yes, it does. Haskell is mostly used for small, single-purpose tools, or it's used to teach FP principles.
The number of repos on Github for Haskell is absolutely minuscule compared to every mainstream language.
There just aren't that many people using Haskell for real projects, nor are there lots of practical libraries for it. (You're free to name some examples if you disagree...)
Perhaps worse, Haskell is hard to learn. Sure your code is super-optimized for a compiler or whatever, but the learning curve is so high that you have to find someone else that's experienced in Haskell to work on your project. That's very, very hard.
> Haskell is mostly used for small, single-purpose tools, or it's used to teach FP principles.
According to whom? If you, how do you come to that conclusion?
> There just aren't that many people using Haskell for real projects, nor are there lots of practical libraries for it. (You're free to name some examples if you disagree...)
I could name many, though I'm not sure they would meet your definition of practical. Could you give me your definition of a practical library, and/or perhaps even better a few practical libraries from your language of choice?
> Perhaps worse, Haskell is hard to learn.
Haskell is no harder to learn than your first programming language where you also had to learn imperative programming semantics and things like Object Oriented programming.
> Sure your code is super-optimized for a compiler or whatever,
It really seems like you don't know much about Haskell. I think you'd be doing yourself a service to take a look.
> but the learning curve is so high that you have to find someone else that's experienced in Haskell to work on your project. That's very, very hard.
Not if you offer remote work and post it to /r/haskell, haskellers.com, and functionaljobs.com
Getting local candidates with previous Haskell experience could be more difficult outside of places like NYC, Austin, Silicon Valley, etc.
I wouldn't advise using it for a start-up unless you have at least one person that is moderately experienced and at the very least created a few libraries.
There are less than 5k Haskell users on Github, and they've released 30k repos.
By comparison, Go has 9k users and 50k repos. And a lot of people say that Go is not that useful of a language because the community is small.
What I'm saying isn't particularly controversial. There's a long thread here where Haskell is brought up frequently in the same context I'm talking about it: https://news.ycombinator.com/item?id=8802454
My definition of practical is this: people use it in practice. They use it for business or for personal projects that other people get use out of.
The core purpose of software is to automate things that, otherwise, people would have to do. What large jobs is Haskell currently automating for people?
> By comparison, Go has 9k users and 50k repos. And a lot of people say that Go is not that useful of a language because the community is small.
Some people call Python too small. Some even claim "Haskell is mostly used for small, single-purpose tools, or it's used to teach FP principles". Some people say a lot of things, that doesn't make it true.
> My definition of practical is this: people use it in practice. They use it for business or for personal projects that other people get use out of.
I use Haskell for freelance clients currently.
> The core purpose of software is to automate things that, otherwise, people would have to do. What large jobs is Haskell currently automating for people?
Standard Chartered is particularly of note, as you can see in this quora question. You can also see other examples of Haskell automating jobs for people:
I don't mind OO / java, I like ruby, I'm hoping rust will be the new language worth using.
I strongly dislike Go for a variety of reasons, mostly dealing with its anti-OO sentiments actually. It has things like "for x := range myArr" but you can't implement that yourself because you actually can't implement either a single and multiple return or implement an iterator/range. The language is full of crap like that, where the programmer is treated like a baby who shouldn't have any power.
Similarly, the language has first class functions, but no functional constructs (map, etc). It doesn't have pattern matching or tuples so multiple-returns feel like a hack. Its error checking is atrocious.
It has no version control or package management worth shit; npm, bundler, etc, all have an idea of "I want something less than this version". In golang, it's worse than C even. They encourage go get, aka "pull from master, surely it won't break" or vendoring. At least in C, you have os package managers to do some of this and pkg-config.
Go is just a terribly designed language in almost every aspect in my opinion. It isn't functional and sucks at OO. It sucks at low level. It sucks at high level. It sucks at large project. It's okay until you need to implement your own type and realize you're a second class citizen.
Hopefully that made sense to you; thanks for asking nicely.
"These posts are fundamentally right about == being poorly designed... but they make things look worse by failing to organize the table.... What a mess! But most of the mess is because of the order of values in the table. By grouping equal values together, you get something more sensible"
http://strilanc.com/visualization/2014/03/27/Better-JS-Equal...