Javascript Absurdities
Javascript is a funky language. Here are some obvious design flaws:
1. Regex test()
method is inconsistent when global flag is set
var pattern = /hi/g;
pattern.test('hi'); //true
pattern.test('hi'); //false
Today at work I spent hours on a witch hunt trying to pinpoint the cause of a bug that was delaying a production release. It ended up coming down to this absurd Javascript quirk within a single “if” statement inside a portion of code that hadn’t been touched in a year.
2. null and undefined
Having separate null and undefined types just adds unnecessary confusion.
The best way to check whether variable is null or undefined is if (varname == null)
. Using the triple equals (which is preferred in almost every other situation) will not catch both types.
3. typeof
typeof [] //"object"
typeof null //"object"
typeof NaN //"number"
Wtf?
4. NaN != NaN
To check if a value is NaN, you have to use isNaN()
.
5. arguments
inside a function is an “Array-like” Object instead of an Array
This is ridiculous. The convention is to use something like var args = Array.prototype.slice.call(arguments)
to convert the “Array-like Object” into an Array (and of course that’s totally clear).
6. Checking deep nested objects is a hassle
Want to check if obj.prop1.thing2.key3 === "hello"
? If obj.prop1.thing2 is not an object, then a TypeError is thrown and your code will abort. So you have to check `obj && obj.prop1 && obj.prop1.thing2 && obj.prop1.thing2.key3 === “hello”. Or you can use a try/catch function or use a utility function (eg. using Lodash or writing your own).
7. Math.abs(null) === 0
null <= 0 //true null < 0 //false null == 0 //false
8. No clear sane way to parse integers
parseInt() is not guaranteed to default to base 10, so you have to explicitly pass in 10 as the base.
parseInt('2424blahblahblah', 10) //NaN
The ”+” sign is commonly used to parse integers, but is a little different and has its own pitfalls as well. For example:
+'' === 0 //true
+true === 1 //true
+false === 0 //true
+'2e3' === 2000 //true
parseInt('2e3', 10) === 2 //true
Be careful:
[1,2,3].map(x => {hi: ‘ok’}) //[undefined, undefined, undefined]
[1,2,3].map(x => ({hi: ‘ok’})) // [Object. Object. Object][1,2,3].map(x => {return {hi: 'ok’}}) // [Object. Object. Object]