DEV Community

Juan Almeida
Juan Almeida

Posted on

Javascript foundations: Types and Special Values

I have read "in Javascript everything is an object" in a lot of articles and books. This is incorrect.

Why?

Javascript it's a dynamic language, but it doesn't mean that does not have types. The official Javascript specification says (http://www.ecma-international.org/ecma-262/10.0/index.html#sec-ecmascript-overview):

A primitive value is a member of one of the following built-in types: Undefined, Null, Boolean, Number, String, and Symbol; an object is a member of the built-in type Object; and a function is a callable object. A function that is associated with an object via a property is called a method.

Means that "3" is not equal to 3, because the first one is a number and the second a string. These two values have different types.

The definition of a type says: type is an intrinsic built-in set of characteristics that uniquely identify the behavior of particular value and distinguishes it from other values which tells the compiler or interpreter how the programmer intends to use the data.

A type in Javascript it's a little bit different from a type in a strongly typed language, where the word type means a lot more, but is enough to affirm that is incorrect to say that everything is an object in Javascript.

Types

Javascript defines seven (in the future eight) built-in types:

  • null
  • undefined
  • boolean
  • number
  • string
  • object
  • symbol (es6)
  • bigint (soon)

All of these types except object are called primitives.

It's important to say: In JavaScript, variables don't have types, values do.

The typeof operator inspect the type of the given value and returns a string with one of the string values listed before.

typeof undefined     === "undefined"; // true
typeof false         === "boolean";   // true
typeof 3             === "number";    // true
typeof "3"           === "string";    // true
typeof { track: 3 }  === "object";    // true
typeof Symbol()      === "symbol";    // true

Exists a special case for null.

typeof null === "object"; // true

In the first implementation of JavaScript, JavaScript values were represented as a type tag and a value. The type tag for objects was 0. null was represented as the NULL pointer (0x00 in most platforms). Consequently, null had 0 as type tag, hence the "object" typeof return value.

A fix was proposed for ECMAScript but was rejected.

undefined, undeclared

A variable that has not been assigned a value is of type undefined.

var a;
typeof a; // "undefined"

An undefined variable is one that has been declared in the accessible scope, but at the moment has no value in it. An undeclared variable is one that has not been declared in the accessible scope. But the typeof operator returns undefined even for undefined or undeclared variables.

var a;
typeof a; // "undefined"
typeof b; // "undefined"

undefined and null are often taken to be interchangeable as either empty values or no values. But null is a special keyword, not an identifier, and thus, you can't treat it as a variable to assign to. However "undefined" is an identifier.

  • null is an empty value or had a value and doesn't anymore.
  • undefined is a missing value or hasn't had value yet.

uninitialized (TDZ)

In ECMAScript 6, accessing a let or const variable before its declaration (within its scope) causes a ReferenceError.

TDZ o temporal dead zone It's very useful to catch programming errors because being able to access a variable before its declaration is strange. If you do so, it is normally by accident and you should be warned about it.

typeof a; // ReferenceError
typeof b; // "undefined"
let a;

If your code tries to access "a" in any way before the "let a" statement is reached, the program will throw the "ReferenceError". Declaring a method that references "a" before it’s defined is okay, as long as the method doesn’t get executed while there is in the TDZ, and "a" will be in the TDZ for as long as the let "a" statement isn’t reached (while the scope has been entered). This snippet won’t throw because return there isn’t executed until after there leaves the TDZ.

Values

Arrays, strings, and numbers are the most basic building blocks of any program, but JavaScript has some unique characteristics with these types that may either delight or confound you. In this article, I will describe the special values. There are several special values spread across the various types that every JS developer needs to be aware of, and use properly.

NaN: Invalid Number

Any mathematic operation you perform without both operands being numbers will result in the operation failing to produce a valid number, in which case you will get the NaN value.

var a = 2 / "a";      // NaN
typeof a === "number" // true

NaN is a kind of "value" that represents a special kind of error condition within the number set. The error condition is: "I tried to perform a mathematic operation but failed, so here's the failed number result instead."

The built-in global utility called "isNaN()" tells us if the value is NaN or not, but the "isNaN()" utility has a fatal flaw. It appears it tried to take the meaning of NaN too literally. Its job is basically: "test if the thing passed in is either not a number or is a number." But that's not quite accurate.

var a = 2 / "foo";
var b = "foo";

a; // NaN
b; // "foo"

isNaN( a ); // true
isNaN( b ); // true - wtf???

Clearly, "foo" is not a number, but it's not the NaN value either!

As of ES6, finally a replacement utility has been provided:

var a = 2 / "foo";
var b = "foo";

Number.isNaN( a ); // true
Number.isNaN( b ); // false

NaN has a particular fact: NaN isn't equal to itself. NaN is the only value in the whole language where that's true; every other value is always equal to itself.

Infinities

Developers from traditional compiled languages like C are probably used to seeing either a compiler error or runtime exception, like "divide by zero", however, in Javascript, this operation is well-defined and results in the value Infinity.

var a = 1 / 0;  // Infinity
var b = -1 / 0; // -Infinity

Once you overflow to either one of the infinities, however, there's no going back. In other words, you can go from finite to infinite but not from infinite back to finite.

Negative Zero

JavaScript has both a normal zero 0 (positive zero +0) and a negative zero -0.

var a = 0 / -3; // -0
var b = 0 * -3; // -0

Addition and subtraction cannot result in a negative zero.

var a = 0;
var b = 0 / -3;

a == b;     // true
a === b;    // true - ??

0 > -0;     // false

a > b;      // false

Object.is(b, -0) // true
Object.is(b, 0)  // false

There are certain applications where developers use the magnitude of one value to represent a piece of information (like the speed of movement per animation frame) and the sign of that number to represent another piece of information (like the direction of that movement). In those applications, if a variable arrives at zero and it loses its sign, then you would lose the information of what direction it was moving in before it arrived at zero. Preserving the sign of zero prevents potentially unwanted information loss.

Summary

JavaScript has seven (eight soon) built-in types: null, undefined, boolean, number, string, object, symbol, bigint (future). They can be identified by the typeof operator.

Variables don't have types, but the values in them do.

undefined is a value that a declared variable can hold, undeclared means a variable has never been declared. The null type has just one value: null, and likewise the undefined type has just the undefined value. undefined is basically the default value in any variable or property if no other value is present.

Top comments (0)