JavaScript Fundamentals: A Simplified Guide

JavaScript Fundamentals: A Simplified Guide

Simplifying JavaScript Fundamentals for Easy Understanding

Introduction

I finished the course Just JavaScript by Dan Abramov.

In this blog post, I wanna share things I've learned.

Mental Models

Mental models make code easier to understand.

They are simplified versions of how we think code works, therefore helping us work with code more effectively.

let x = 10;
let y = x;
x = 0;

Here's what happens:

  1. We set a variable called x to 10.

  2. Then, we create another variable called y and give it the same value as x.

  3. After that, we change the value of x to 0.

In our thoughts, it goes like this:

  1. x equals 10.

  2. Then we make y equal to x, which means x is also 10.

  3. Later, we change the value of x to 0.

  4. So now, x is 0 and y is still 10.

Values and code

In JavaScript, values and code exist independently. There are two categories of values:

  • Primitive Values

  • Objects and Functions

Expressions in JavaScript are like questions we ask in our code. They don't show values on their own, but JavaScript gives us the answers. For example, when we ask 2 + 2, the answer is 4.

The typeof operator allows us to check the type of a value:

console.log(2 + 2); // 4
console.log(typeof(2)); // "number"
console.log(typeof({})); // "object"
console.log(typeof([])); // "object"
console.log(typeof(x => x * 2)); // "function"
console.log(typeof("hello")); // "string"
console.log(typeof(undefined)); // "undefined"

Primitive Values

Primitive values in JavaScript have always existed, and we cannot create new primitive types. They are immutable, which means they cannot be changed once created.

Undefined: Represents an undefined or unknown value.

let x;
console.log(variable); // undefined

// Variable has no value yet.

Null: Represents the absence of a value.

let value = null;
console.log(value); // null

// Variable intentionally has no value.

Boolean: Represents true or false.

let isWaterWet = true;
let isFireWet = !isWaterWet;
console.log(isWaterWet); // true
console.log(isFireWet); // false

Numbers: Represent numerical values.

let number = 28;
console.log(number); // 28

NaN: Stands for "Not a Number" and represents an invalid numeric value.

let result = "Hello" / 2;
console.log(result); // NaN

BigInts: Handles large whole numbers.

let bigNumber = 12345678901234567890n;
console.log(bigNumber); // 12345678901234567890n

String: Represents text.

let world = "Shinobi World";
console.log(world); // "Shinobi World"

Objects and Functions

Objects

Objects let us create our own values. They can be arrays, dates, and other non-primitive types. We can change them because they're mutable.

When we use {} in JavaScript, it makes a new object every time. So, even if we use {} more than once, each one will be its own separate object.

let anime = {};
let manga = {};

console.log(anime === manga); // false (not the same object)

Functions

Functions are special and can be thought of as objects. We use parentheses () after their name to call functions, and they execute their code, which might give us a result.

function jutsu() {
  console.log('Shadow Clones');
}

jutsu(); // Calling the function

Functions can be changed, so we can make them behave differently or redefine them.

let multiply = function (a, b) {
  return a * b;
};

multiply = function (a, b) {
  return a + b;
};

console.log(multiply(2, 3)); // 5

When a function runs, it creates a new function value.

for (let i = 0; i < 7; i++) {
  console.log({});
}

/* The line of code console.log({}) creates a brand new object every time it is executed within the loop. */

Equality of Values

Strict Equality (===): checks the value and the type of the compared values.

console.log(2 === 2); // true
console.log("Boruto" === "Boruto"); // true

Loose Equality (==): checks only the value of the compared values.

  • Before comparing values, JavaScript does type coercion, which means it converts a value from one type to another.
console.log(2 == "2"); // true

/* True because `==` changes the text '2' into the number 2 and then checks if they are the same */

Same Value Equality - Object.is(): a way to compare two values

console.log(Object.is(2, 2)); // true
console.log(Object.is({}, {})); // false

/* False because each {} creates a new object with a different memory reference */

Properties in JavaScript

Properties are data that belong to objects and are grouped together. Each property always directly points to a value and cannot reference another property or a variable.

let boruto = { surname: 'Uzumaki', age: 16 };

console.log(boruto.age); // 64
console.log(boruto.power); // undefined

/* Returns undefined because there is no "power" property defined in the boruto object */

They must have unique names within an object, and they are case-sensitive. This means having properties with the same or similar names but different casing will result in separate and independent properties.

const character = { name: 'Boruto Uzumaki', age: 16, Age: 0 };
console.log(character.name); // "Boruto Uzumaki"
console.log(character.age); // 16
console.log(character.Age); // 0

Mutation

Objects can be put inside other objects. Changing a property of an object is called mutation and it changes the object itself.

const character = { name: 'Boruto Uzumaki', age: 16};
character.age = 4;
console.log(character.age); // 4

Using const to declare a variable stops us from changing what it refers to, but we can still modify an object's properties through object mutation.

Prototypes

Prototypes help us share features between objects. But if we change a feature in one object, it won't affect its prototype. They are key to creating classes and inheritance in JavaScript.

const boruto = { jutsu: 'Shadow Clones' };
const mitsuki = { __proto__: boruto, age: 19 };

console.log(mitsuki.jutsu); // 'Shadow Clones'

Prototype chaining in JavaScript is like creating a family tree for objects, where they can share and get traits from their parents and grandparents:

const sarada = { 
   strong: true 
};

const boruto = { __proto__: sarada,  jutsu: 'Shadow Clones' };

let mitsuki = { 
    __proto__: boruto, 
    age: 19 
};

console.log(mitsuki.strong); // true

The hasOwnProperty method checks if an object has its own property, not considering the prototype chain, and only considers properties directly defined on the object.

const boruto = { jutsu: 'Shadow Clones' };
const mitsuki = { __proto__: boruto, age: 19 };


console.log(mitsuki.hasOwnProperty('jutsu')); // false
console.log(mitsuki.hasOwnProperty('age')); // true

Review

I wish I had done this course earlier.

I strongly recommend it to anyone who wants to dive deeper into JavaScript.