Heya, nice to see you again in another article, today's topic is kind off functional programming, I thought it my be nice to get back the basics and talk about types which is one of my favourite topics.
So why not have a series that's dedicated to the typesystem that JS has?
In this article I'll to go all beasty about types and why you should really care about types, so hold tight and let's go.
"Stop using double equal, tripe equal for the way", you often see this recommendation in some courses, blogs, and even books that favors the tripe equal ===
over the double equal ==
as they claim it's better in terms of handling corner cases. HELL NO
I won't argue that back in time I believed such claim and even spread it in some of my courses, articles. But meh, we all do silly things.
So, let's get right into our topic and understand why I am so that irritated of this claim
What types does JS have?
Surely you know what types the language you use supports, but bare with me and let's revisit them swiftly.
-
Primitives
- String
- Number
- Undefined, NULL
- Symbol
- Boolean
-
Object
- object (The object notation or an instance of a class maybe)
- Array
- Function
All the primitive types are treated by javascript as non-reference values a.k.a they get stored on the stack not the heap (We'll have another article about that I promise).
And all the descendendants of the Object
type are treated as Referenceable
values, as they get stored on the heap
and their reference is stored on the stack
The typeof Operator
This operator is kinda special as it's the only operator in javascript that can access non-existing variables in any scope, let's see the following example.
Undeclared
console.log(typeof undeclared) // undefined
Apparently, the variable undeclared
doesn't exist in any scope, yet the typeof
can access it, but what distrubs me that it returns undefined
:/
Well, it might seem reasonable, but IMHO, I like to think of undefined
as a representation of no value, more like the absence of a value, and I might assume that you too think of it like that, more like a placeholder to an upcoming value, consider the following example.
class User {
protected db: Database
constructor(db: Database) {
this.db = db
}
}
You're expecting the variable db to be instance of some Database
entity, maybe you're injecting it to your User
model to handle incoming requests related to database persistency.
Apart from that, what is the value of db
before you pass it any instance? Yup, it's undefined
, you haven't setted a value for it yet, so the absence of a value is represented by the keyword undefined
, hopefully that makes sense.
But if so, what's the problem with returning undefined
using typeof
operator for non-existing variable?
Well, I agree with Kyle Simpson that this is some sort of confusion, using the same data type for two separate concepts is not accurate, JavaScript could've introduced new type called undeclared
to indicate that some variable is not defined in any accessible scope.
Further, neither me nor Kyle thought of this mental models by ourselves nor did anyone has this mental model, actually the EcmaScript guidelines says so.
But meh, adding something like this may cause a lot of bugs to existing code basis, you never know if someone uses such code.
Null is an object
let v = null
console.log(typeof v) // object
One of the weirdest parts of JavasScript, that it treats the null
as if it's an object.
Well, I think there are two mental models that justify this behavior.
- Null is a representation of an empty object
- Null is just equal to undefined and that's a JS bug
Well let's walk through each behaviour and I'll let you decide which one makes more sense.
Null is an empty object
Consider the following piece of code.
let nullObject = Object.create(null)
console.log(nullObject)
The output of this code would be something like [Object: null prototype] {}
, thus there are some opinions or thoughts that the null
type in JS is treated as object
because it can be used as a prototype
to other objects a.k.a if you want to create functionless -if you will- object which has no prototypes, therefore, it has any built-in support from JS object functionalities.
let nullObject = Object.create(null)
let anotherObject = {}
console.log(anotherObject.toString()) // [Object object]
console.log(nullObject.toString()) // Throws an error
And once again, I am not making this up, that's what the EcmaScript specs says about the null type
Null is undefined
I think this way of thinking is based on the idea that console.log(null == undefined)
returns true
or maybe you're like me, shifting from another language (PHP in my case) to JavaScript, either way, I think those both mental models are incorrect in some sense.
The first one totally ignores the fact that console.log(null === undefined)
returns false
which makes them completely different, and the second one judges JavaScript by other languages'rules, which is more worse.
If you're doing JavaScript, do it in JavaScript way - Panda's Law #2
Yet, there are some corner cases that I'd like to treat null and undefined as equal types: If it makes sense!!
If I can write more concise code using the fact that they're equal in abstract (We'll explain this later in the Equality section of this series), sure I'll do so.
Arrays are objects
This one is quite easy I'd say, but let's walk through it.
let ages = [20, 21, 26, 42]
console.log(typeof ages) // "object"
This one is completely reasonable, as I mentioned earlier, the V8 engine treats arrays and objects alike in some ways to reduce the duplications in memory allocation (I promise there will an article for that..)
Therefore, if you want to make sure that some variable is an array, you have to use the Array constructor
let ages = [20, 21, 26, 42]
console.log(Array.isArray(ages)) // true
And I think the rest of the types are quite reasonable about, like typeof function(){}
returns "function"
and so on.
The special type NaN
The #1 misunderstood type in JS, I think if IEEE was paid 1 dollar for everytime the NaN thought to be not a number they would've been #1 in Nasdaq..
Yeh the NaN is made to be though of as Not a number
but meh, not the real meaning of not being a number!!
console.log(typeof NaN) // number
Like c'mon! the typeof
operator says it's a number :"
I'd blame IEEE for not calling it NavN
which stands for Not a valid number
or NarN
which stands for Not a representable number
because that's what NaNs are.
consider the following examples.
console.log(Number('abc')) // NaN
console.log(Number({ x: 1, y: 2 })) // NaN
console.log(Number([1, 2, 3, 4])) // NaN
console.log(Number('5')) // 5
console.log(Number(true)) // 1
So NaNs actually are numbers, but special number that cannot be represented in a numeric form, and I'll refer back to why we're having this argument.
Now that's done with, I'll see you in the next part ^^
Have a nice drink and a wish you a very pleasing day, Cheerio 💜
Top comments (0)