• FrontendJoy
  • Posts
  • ✨🧱 JavaScript Data Types: 27 Quick Questions You Need To Master

✨🧱 JavaScript Data Types: 27 Quick Questions You Need To Master

1. What is a data type?

Every value in JavaScript has a specific type.

This type determines what operations can be performed on the value and how it's stored 🗳️.

This is known as the data type.

2. How many data types?

There are 8 data types in JavaScript: number, string, boolean, null, undefined, bigint, symbol and object.


JavaScript data types with examples

3. What is a primitive data type?

Every type except the object type 😅.

So, there are 7 primitive data types: string, number, boolean, undefined, null, symbol, bigint.

Primitive values have the following characteristics:

  • They don't have methods or properties.

  • They are immutable: you cannot modify the value once it is created.

  • They are directly stored in the memory stack.

let sample = 'immutable'
console.log(sample) // "immutable"
sample[0] = 'V' // changing the first letter to V
console.log(sample) //"immutable" (since the string cannot change)

What the heck is the memory stack?

A JavaScript program has a memory where it stores variables/values for later access.

That memory consists of the stack and the heap.

  • Stack: Stores static data (data with a fixed size). Since primitive values are immutable and won't change, they will be stored here.

  • Heap: Stores object values. The heap's size can change during the code execution to accommodate object value changes.

4. What is a non-primitive data type?

The object type is the only non-primitive data type.

This includes: object literals ({ name: "Fatou" }), functions (function sayHi(){}), arrays ([1, 2, 3]), etc.

There is a crucial difference between primitive and non-primitive data types.

👉 When a variable contains a non-primitive data type, it doesn't hold the actual object value.

Instead, it contains a reference to that object in memory (i.e., in the heap).

Think of a reference like an address.

House != Address

However, if I do things like:

  • Send a gift to {fillInYourAdress}.

  • Paint the house at address {fillInYourAdress}.

It will affect your house.

In the JavaScript world, this is equivalent to the following code:

const house = {
   floors: 2,
   gifts: [],
   color: "blue"
}
house.gifts.push("Red dress")
house.color = "red"

Keep this distinction in mind when passing objects to functions.

In the following example, the code modifies the original array since it is passed to the function as an address:

function addUser(arr){
   const randomId = "123"
   arr.push({ id: randomId } );
   return arr;
}

const users = [];
console.log(users); // []
const newUsers = addUser(users);
console.log(newUsers); // [{ id: ... }]
console.log(users); // [{ id: ... }] (since users was modified)

5. How do you get the type of a value?

You can use typeof to get the type of a value.

const name = "Ndeye Fatou Diop";
console.log(typeof "Hello") // "string"
console.log(typeof("Hi")) // "string"
console.log(typeof name) // "string"

💡 Note: This method doesn't work for null because typeof null returns object 😅. To safely check if value is an object, you need to do value != null && typeof value === "object"

6. What does typeof (() => {}) return?

This is the other exception with typeof.

typeof fn returns function instead of object 🤦‍♀️.

const sayHi = (name) => console.log(`Hi, ${name}`)
console.log(typeof sayHi); // "function"

7. How do you check if a value is an array in JavaScript?

typeof arr returns object since arrays are objects.

Instead, you can use Array.isArray(value).

const nums = [1, 2, 3];
console.log(Array.isArray(nums)); // true
console.log(Array.isArray({})); // false

8. What is the difference between number and bigint?

Only integers within the range [-9007199254740991, 9007199254740991] are safe to manipulate in JavaScript.

Integers outside this range can give incorrect mathematical results.

For example, 9007199254740993 - 9007199254740992 will return 0 instead of 1.

BigInt was introduced for integers outside this range. Any integer can be converted to a bigint by appending n to it or using BigInt(...)

9007199254740993n - 9007199254740992n will correctly return 1n.

💡 Tip: You can get the min/max safe integers with Number.MIN_SAFE_INTEGER and Number.MAX_SAFE_INTEGER.

9. What is the difference between null and undefined?

There is a slight difference.

  • undefined conveys a value that hasn't been defined yet. It's like you just bought a new house, and someone asks about the swimming pool 🏊‍♂️. You haven't even thought about it yet — it's undefined!

  • null conveys a value that has been set to "empty". It's like you bought the house and decided there wouldn't be a swimming pool (since you're too broke for it 😅).

💡 Note: Don't rely on that distinction in your code. Just consider any value null or undefined as empty.

10. What is a property?

Objects have properties.

Each property associates a key with a value.

For example, the object me has the properties name, age, etc.

const me = {
  name: "Fatou",
  age: 30,
  job: "Software Engineer"
}

Three things to know about keys

  1. Only string or symbol values are allowed as keys. Any other value will be converted to string through coercion (see Question #12)

  2. They are case-sensitive

  3. You need [] to access keys with space separation

const obj = {
  "first name": "Fatou"
};
console.log(obj.first name); // Doesn't work
console.log(obj["first name"]); // "Fatou"

11. What is a method?

Methods are special properties that associate a key with a function.

That function can only be accessed through the object like this:

const me = {
  name: "Ndeye Fatou Diop",
  sayHi(){
    console.log(`Hi, my name is ${this.name}`)
  },
  sayHelloWorld(){
    console.log("Hello World")
  }
}

me.sayHi(); // Hi, my name is Ndeye Fatou Diop
const sayHelloFn = me.sayHelloWorld;
sayHelloFn();

💡 Note: Be careful with the this object in the sayHi function. If the function was called like this, const fn = me.sayHi; fn();, this != me. You can learn more about this rule here.

12. What is coercion?

Remember question #1?

A data type only supports certain operations.

For example, we can add numbers like this 1 + 2.

What happens when we try "invalid" operations like "8" + 9?

👉 Coercion happens.

It is when JavaScript implicitly converts values from one data type to another.

In the example above, JavaScript will convert 9 to the string "9" and return "8" + "9" => "89".

More examples of coercion:

const result = "9" - 5; // returns 4 since "9" is coerced into the number `9`

const sum = true + false; // returns 1 since true is coerced into 1 and false into 0

💡 Notes: There are coercion rules, but you don't need to remember them all. Instead, avoid comparing apples and oranges and invalid operations 😅.

13. What is a falsy value? What is the opposite of it? Can you name all falsy values?

The simplest answer: If Boolean(value) returns false, value is falsy.

So, every falsy value will be coerced to false when JavaScript expects a boolean value (see Question #12).

Examples:

// value is falsy

if(value) {
  // Not reachable since `value` will be coerced into `false`
}

const name = value && "myValueHere"; // `name` will be equal to `value` since `value` will be coerced to false

There are only 10 falsy values:

  • false

  • 0, +0, -0, 0n, NaN

  • empty string: "", '', etc.

  • null

  • undefined

  • document.all: the only falsy object

If a value is not falsy (i.e., not present in this list), it is truthy.

14. How do you convert a value to its boolean representation?

You have two options:

  • Option #1: Boolean(value)

  • Option #2 (better): !!value

console.log(Boolean(1)); // true
console.log(Boolean(0)); // false
console.log(!!1); // true
console.log(!!0); // false

15. What is the difference between == and ===?

=== is like == except no coercion happens, and the types need to be the same.

In fact, == will return true if the two values are equal after JavaScript coercion kicks in.

For example, 1 == true returns true because JavaScript will coerce 1 into a boolean. Since 1 is truthy (see Question #13), it will be equivalent to true.

Conversely, 1 === true will return false since the types differ.

💡 Tip: Never use == unless for checking if a value is null/undefined. Otherwise, coercion may kick in, resulting in unexpected results. For example [] == ![] returns true since both sides are coerced into numbers ([] => 0, ![] => false => 0 since [] is truthy)

16. Why does 0.1 + 0.2 === 0.3 return false?

0.1 and 0.2 are floating point numbers.

In JavaScript (and many other languages), floating-point numbers are represented using the IEEE 754 standard.

Unfortunately, numbers like 0.1 and 0.2 cannot be represented precisely in this standard, leading to a loss of precision.

As a result, 0.1 + 0.2 is equivalent to approximate(0.1) + approximate(0.2), which results in something slightly different from 0.3.

17. Why is {} === {} returning false?

This question is easy if you understand Question #4.

{} are objects. As a result, each one stores a different reference pointing to a different value in memory (heap).

Since those references (i.e., addresses) are different, the comparison returns false.

18. What are the different ways to access an object property?

There are two options (using dot notation or bracket notation).

Let's say we have the following object, and we want to access the name property:

const me = {
  name: "Ndeye Fatou Diop",
  job: "Software Engineer",
  "way of life": "Coding"
}

We can do:

  • me.name

  • me["name"]

💡 Note: For properties with spaces like "way of life", we can only use me["way of life"].

19. How do you safely do obj.value when obj can be undefined or null?

We have two options:

  • Option #1: obj != null ? obj.value : undefined

  • Option #2 (better): Use the optional chaining operator like this obj?.value

20. How do you loop through the values of an array or object?

For an array

const arr = [1, 2, 3]

// Option 1: Use for...of
for(let x of arr) {
  console.log(x)
}

// Option 2: Use for with indices
for(let i = 0; i < arr.length; i++) {
  console.log(arr[i])
}

// Option 3: Use forEach
arr.forEach(x => {
  console.log(x)
})

For an object

const obj = {
  name: "Fatou",
  age: 30
}

// Option 1: Use `Object.keys`
Object.keys(obj).forEach(k => {
   console.log(obj[k])
})

// Option 2: Use `Object.values`
Object.values(obj).forEach(x => {
   console.log(x)
})

// Option 3: Use `Object.entries`
Object.entries(obj).forEach(([k, x]) => {
   console.log(x)
})

💡 Important: Avoid for...in since it may produce unexpected results.

21. What is prototypal inheritance?

Every object in JavaScript has a hidden property [[Prototype]] called the prototype that is either an object or undefined.

This property can be accessed via obj.__proto__.

Where does the prototype come from?

There are multiple ways to set an object prototype:

Option #1: Just create the object

Every object will have a default prototype when set.

For example,

  • The prototype of array objects is Array.prototype

  • the prototype of objects like { name: "Fatou"} is Object.prototype

  • etc.

Option #2: Explicitly set the prototype

const car = {
  wheels: 4
};
const bmw = {
  brand: "BMW"
};

bmw.__proto__ = car; // bmw.[[Prototype]] is equal to car

Option #3: Create the object with a given function

function Car(brand){
  this.brand = brand
}
const bmw = new Car("BMW"); // bmw.[[Prototype]] has the following shape: { constructor: Car, … }

Option #4: Create the object with Object.create

const car = {
  wheels: 4
};
const bmw = Object.create(car); // bmw.[[Prototype]] is equal to car
bmw.brand = "BMW";

What is the prototype used for?

So, every object has a prototype. Now what? 😅

When you try to access a method or property on an object, JavaScript will first examine the object.

When no property/method can be found, JavaScript will look into the prototype object.

Three things can happen:

  1. The property/method exists on the prototype object => JavaScript will return it

  2. The prototype method is undefined => JavaScript will return undefined

  3. The prototype method is not undefined => Inheritance kicks in. Since the prototype is an object, it has its own prototype. So JavaScript will look into the prototype of the prototype. It will continue doing so until it finds the property/method or the prototype becomes undefined.

This is prototypal inheritance 😀. We inherit the properties/methods of the prototype. The ultimate prototype is Object.prototype and Object.prototype.__proto__ === undefined.

In the example below, bmw object does not have the wheels property, so the one on car will be returned.

const car = {
  wheels: 4
};
const bmw = {
  brand: "BMW",
  print(){
    console.log(`My brand is ${this.brand} and I have ${this.wheels} wheels`);
  }
};

bmw.__proto__ = car; // Sets bmw.[[Prototype]] to car
bmw.print(); //"My brand is BMW and I have 4 wheels"

💡 Note: If you want to learn more about prototypal inheritance? Check this great post from @lydiahallie.

22. How do you check whether a property exists in an object?

Your first instinct may be to use obj.value !== undefined, but this can go wrong in these cases:

  • obj is undefined

  • obj.value is present by undefined

  • value is present in the prototype chain (see Question #21)

We can try value in obj, but this breaks when obj is undefined or null.

The safest way to achieve this? 👉 obj?.hasOwnProperty(value)

23. Why can we call methods like .trim() on string values?

Primitive values like strings have no methods.

So, how the heck does this work? 😅

Well, it is through a neat feature called auto-boxing ✨

What is auto-boxing in JavaScript?

Every primitive type except null and undefined has an associated object wrapper class (see table below).

Data Type

Object wrapper

null

N/A

undefined

N/A

number

Number

string

String

boolean

Boolean

bigint

BigInt

symbol

Symbol

Auto-boxing is when JavaScript temporarily converts a primitive type to its corresponding object wrapper when certain methods or properties are accessed.

Let's look at an example:

const name = "Ndeye Fatou Diop   ";
const cleanName = name.trim(); // cleanName = "Ndeye Fatou Diop"

When we do name.trim(), name is a primitive value and doesn't have methods. JavaScript will then:

  1. Convert name to new String(name), which is an object.

  2. Access the trim method on the String object, returning "Ndeye Fatou Diop"

  3. Return the result

24. Can you give 3 ways to create an undefined value?

  • Option #1: Explicitly set the value to undefined

let age = undefined;
  • Option #2: Declare a variable without an initial value

let age;
var name;
  • Option #3: Access a property/method that doesn't exist

const me = {
  name: "Ndeye Fatou Diop"
}
let age = me.age; // `age` is undefined because it doesn't exist in the object

25. What is the difference between shallow copy and deep copy?

First, what is a copy?

Let's say I have an array arr1, and I want to create a copy of that array arr2.

I can't do const arr2 = arr1 since the arrays will point to the same object, and any modification to arr2 will affect arr1 (see Question #3).

So what is the solution?

👉 const arr2 = [...arr1];

This will make sure the two arrays point to different objects in memory.

But there is a catch 😅.

This works fine when the arrays contain primitive values like const arr1 = [1, 2, 3], but what if the arrays contain objects like const arr1 = [ { name: "Fatou"}]?

What happens when I do arr2[0].name = "Thomas"?

Will arr1[0] be affected? 👉 Yes.

Because arr2 still contains a list of references that are the same as in arr1. So, any modification will affect the objects these references point to.

The copy we did was a shallow copy.

A deep copy is when we create new references for every object, so any modification does not affect the original objects.

In the example above, we can do a deep copy this way:

const arr1 = [ { name: "Fatou"}]

// Option #1: This will only work when every value can be serialized
const arr2 = JSON.parse(JSON.stringify(arr1))

// Option #2: Use `structuredClone`
const arr2 = structuredClone(arr1)

💡 Important: Deep copy is more expensive than shallow copy. Make sure you actually need it before reaching for it.

26. What is the result of Symbol("name") === Symbol("name")

👉 False.

Every call to Symbol returns a different value, even if the descriptions are the same.

27. Can you change the data type of a variable?

Variables don't have a type; values have 😅.

In fact, when we have the following code, typeof name is equivalent to typeof "Ndeye Fatou Diop" which returns "string".

const name = "Ndeye Fatou Diop"
const type = typeof name; // returns "string"

As a result, since variables declared with var and let can have their values changed, their types can also change.

let x = "Ndeye Fatou Diop"
console.log(typeof x); // logs "string"

x = 45;
console.log(typeof x); // logs "number"

Thank you for reading this post 🙏.

If you liked this article, join my FREE newsletter, FrontendJoy.

If you want daily tips, find me on X/Twitter.

Reply

or to participate.