2. Primitive Types
Tags: javascript, webdev, beginners, programming
Published: 2022-01-12 13:51:05

### **Reference**

- [JavaScript data types and data structures — MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Primitive_values)  

### **Articles**

- [How numbers are encoded in JavaScript — Dr. Axel Rauschmayer](http://2ality.com/2012/04/number-encoding.html) 
- [What You Need to Know About JavaScript Number Type — Max Wizard K](https://indepth.dev/posts/1139/here-is-what-you-need-to-know-about-javascripts-number-type) 
- [https://indepth.dev/posts/1018/the-mechanics-behind-exponent-bias-in-floating-point](https://indepth.dev/posts/1018/the-mechanics-behind-exponent-bias-in-floating-point)
- [https://indepth.dev/posts/1019/the-simple-math-behind-decimal-binary-conversion-algorithms](https://indepth.dev/posts/1019/the-simple-math-behind-decimal-binary-conversion-algorithms)
- [What Every JavaScript Developer Should Know About Floating Point Numbers — Chewxy](https://blog.chewxy.com/2014/02/24/what-every-javascript-developer-should-know-about-floating-point-numbers/) 
- [The Secret Life of JavaScript Primitives — Angus Croll](https://javascriptweblog.wordpress.com/2010/09/27/the-secret-life-of-javascript-primitives/) 
- [https://includestdio.tistory.com/26](https://includestdio.tistory.com/26)  
- [(Not) Everything in JavaScript is an Object — Daniel Li](https://dev.to/d4nyll/not-everything-in-javascript-is-an-object) 
- [Diving Deeper in JavaScripts Objects — Arfat Salman](https://blog.bitsrc.io/diving-deeper-in-javascripts-objects-318b1e13dc12) Later
- [The differences between Object.freeze() vs Const in JavaScript — Bolaji Ayodeji](https://medium.com/@bolajiayodeji/the-differences-between-object-freeze-vs-const-in-javascript-4eacea534d7c) Later

---

## Definition

Data type **except object** which is **immutable**.

There are 6 types in primitive types. **Boolean type** represents the logical entitiy which is true or false. **Null type** is just null. **Undefined type** represents when variable has not been assigned a value. **Symbol type** is an unique value which can be used as key of an object property. **String type** represents the textual data. **BigInt type** represent numeric value that exceeds safe integer limit for **Number type**.

---

## Number type

Number type represents all numeric value; integers, floating-point number, +Infinity , -Infinity, NaN. Values are range from -(2^53-1) ~ (2^53-1) represented in ***64 bit IEEE***(***IEEE*** 754 ***Double Precision***) format. 

### 0.1 + 0.2 == 0.3 // false

Through this example, I will illustrate how number is stored and evaluated in Javascript. 

Why `0.1` + `0.2` differs from `0.3`?
#### 1. Scientific notation
$$significant \times base^{exponent}$$

- significant: number of significant digits. It's also called Mantissa or Precision.
- base: numeric system base.
- exponent: how many  places a radix point moved from the original number.

A normalized form is a number which is represented as a scientific notation with
- one nonzero decimal digit before radix point

ex) 1.1 x 10^(-2), 1.01 x 2^(-2)

In binary base, normalized format always has 1 before radix point.

#### 2. how numbers are stored
There are two types; single precision and double precision. As javascript uses double precision, the total bits are 64, sign takes 1bit, exponent takes 11 bits, and significant takes 52bits.
![](https://images.velog.io/images/gtfo/post/317d0146-6842-4aca-977b-d2a42682698b/image.png)

1. sign
if number is positive, 0 and negative, 1.

2. exponent
	Exponent is stored in **offset binary format**. Offset binary format works in following steps.
    1) Find offset K which, $$K = 2^{n-1}-1$$ for n bits.
    2) add K to given number
    3) convert it to binary
  Advantage compare to two's component is that we can compare number using lexicographical order.
  
  Ex) convert 3 in 4 bits using offset binary format.
  	1. K = 7
      2. 3+7 = 10
      3. 10 = 1010_(2)
 3. significant
 As we only consider binary normalized form, 1 always exists before radix point. So we ignore the most front `1`.

#### 3. convert decimal fraction to binary
It's better to show in example.

Ex) convert 0.375 in binary form.
- 0.375 X 2 = 0 + 0.75
- 0.75 X 2 = 1 + 0.5
- 0.5 X 2 = 1 + 0

-> 0.375_(10) = 0.011\_(2) = 0 X 2^-1 + 1 X 2^-2 + 1 X 2^-3

#### 4. Calculating 0.1 + 0.2
1. first transform to binary
0.1 X 2 = 0 + 0.2
0.2 X 2 = 0 + 0.4
0.4 x 2 = 0 + 0.8
0.8 x 2 = 1 + 0.6
0.6 x 2 = 1 + 0.2
0.2 x 2 = 0 + 0.4
...
-> 0.1_(10) = 0.0001100110011...\_(2) = $$0.0\overline{0011}$$\_(2)

2. represent into normalized scientific notation
	0.0001100110011...
    = 1.1001100110011..._(2) x 2^(-4)
    = $$1.\overline{1001}$$ x 2^(-4)
 3. transform to IEEE 754 form
 	1. exponent
    	
        K = 2^(11-1) - 1 = 1023, as exponent is -4, -4 + 1023 = 1019
        1019_(10) = 01111111011\_(2)
   	2. significant
    
     ignore `1` before readix
     -> 100110011001... 
     As number exceed 52bits, we should round number.
     -> 10011001...10011010 (52bits)

... in total 0.1 = 
  0 01111111011 10011001...10011010_(2)
  
  Using same method, we can calculate 0.2, which is 
  0 01111111100 10011001...10011010_(2)
  
  We add these number in a scientific notation form. With all these procedures, we have rounded number 3 times in total. However, if we just transform 0.3 into binary IEEE 754 form, we just round 1 time. So, this is why there's difference between two values.
  
---

### Number.MAX_SAFE_INTEGER
#### Definition
Largest integer n such that n and n+1 are both exactly representable as Number value.
Number.MAX_SAFE_INTEGER = 9007199254740991 = $$2^{53}-1$$
But, it's not the largest integer that can be represented.

Number.MAX_SAFE_INTEGER = 9007199254740992 =  1111...111(53bits)
= 1.111...11(52bits) x $$2^{52}$$
= 0 10000110011 1111...1111(52bits)

We used all places in significant part. Thats why it's the largest value that represented properly.

#### What happens to number beyond Number.MAX_SAFE_INTEGER
Straight to the point, only even integer beyond Number.MAX_SAFE_INTEGER can be represented. Odd numbers are rounded to the nearest even number. Why?

Number.MAX_SAFE_INTEGER+1 = 9007199254740992 = 1.111...11(52bits) x $$2^{52}$$ + 1
= 1.000..00(52bits) x $$2^{53}$$ 
This is okay. However, as the significant part is full with 52bits, the only way to represent bigger number is using exponent part. Using exponent part means that we add number multiplied by 2.

For example, 
1.0000...1(52bits) x  $$2^{53}$$  == 1000...0010_(2) (53bits) = 9007199254740994\_(10)

---

### NaN & Infinity
NaN and Infinity are both expressed in IEEE form. NaN has exponent part full of 1's and significant part doesn't matters except it is all 0's. This is why we get
``` jsx
console.log(NaN == NaN) // false
```
Because, NaN is not fixed number. 

Infinity has exponent part full of 1's and all 0's in significant part. 

---
## Wrapper objects
As primitive data types are not object, We cannot access its properties or methods. However, it is possible.
``` jsx
name = 'John';
name.length; // 4
name.indexOf('J'); // 0
```
Why does this happens? 

If we treat primitve value like an object(access to method), Javascript automatically creats a wrapper object that wrap this value as an object. This object is used for while and discarded right away. This is called **Auto-boxing**.

Wrapper objects for number values are instances of **_Number_**, string values are wrapped by instances of **_String_** and the type for a boolean’s wrapper is **_Boolean_**. As you can see, `null` and `undefined` cannot be wrapped. 

``` jsx
typeof "abc"; //"string"
typeof String("abc"); //"string"
typeof new String("abc"); //"object"
typeof (new String("abc")).valueOf(); //"string"
```
Also, we can store wrapper object by assigning it to a variable. 
``` jsx
const pet = new String("dog")
typeof pet; // "object"
pet === "dog"; // false
```