DEV Community

Cover image for The Joy of Learning the Basics Again
Sabi Mantock
Sabi Mantock

Posted on

The Joy of Learning the Basics Again

I’ve been revisiting JavaScript recently.

Not because I’ve never used it before, but because I realised there were a lot of things I could recognise when I saw them in code without feeling fully confident that I understood them properly.

That distinction started bothering me.

I could read JavaScript.

I could follow what was happening.

But being able to look at code and understand it is not always the same as being able to sit down with a blank file and write it confidently yourself.

So I decided to go back to the basics.

And weirdly enough, I’ve been enjoying it a lot more than I expected.

There’s something satisfying about revisiting something familiar and realising you understand it differently the second time around.

Starting from the beginning again

I started with things like:

const userName = "Sabi";
const role = "admin";
let postCount = 0;
Enter fullscreen mode Exit fullscreen mode

Very basic stuff.

At first, part of me wanted to rush through it because I already knew what const and let were.

But slowing down actually helped.

Instead of just remembering that let can be reassigned and const cannot, I started thinking more deliberately about why I would choose one over the other.

That set the tone for the rest of the refresher.

I wasn’t just trying to remember syntax.

I wanted the concepts to actually make sense.

Functions exposed a few gaps

Functions were another area where I thought I was already comfortable.

Then I started paying more attention to the smaller details.

For example:

function checkAccess(role) {
    return role === "admin";
}

checkAccess("admin");
Enter fullscreen mode Exit fullscreen mode

role is the parameter.

"admin" is the argument.

Simple distinction, but it reminded me how easy it is to skip over small concepts because you’ve seen them so many times.

Those gaps add up.

Arrays were where things started getting more interesting

I revisited arrays and loops, then moved into:

map()
filter()
find()
some()
every()
reduce()
Enter fullscreen mode Exit fullscreen mode

These are methods I’ve seen and used before, but going through them one by one made the differences much clearer.

For example:

const users = [
    { name: "Sabi", role: "admin" },
    { name: "Kong", role: "member" },
    { name: "Vandal", role: "member" }
];
Enter fullscreen mode Exit fullscreen mode

To get all admins:

const admins = users.filter(
    (user) => user.role === "admin"
);
Enter fullscreen mode Exit fullscreen mode

To get one particular user:

const user = users.find(
    (user) => user.name === "Vandal"
);
Enter fullscreen mode Exit fullscreen mode

Same array.

Different intention.

That sounds obvious, but writing these things myself made them stick much better than just reading examples.

I had been using callbacks without really thinking about them

This was one of the more useful moments.

Something like:

users.filter((user) => user.role === "admin");
Enter fullscreen mode Exit fullscreen mode

looks completely normal.

But that function inside filter() is a callback.

When I recreated the idea manually:

function welcomeUser(name) {
    console.log(`Welcome, ${name}`);
}

function welcomeUsers(users, callback) {
    for (let i = 0; i < users.length; i++) {
        callback(users[i]);
    }
}
Enter fullscreen mode Exit fullscreen mode

it clicked more clearly.

A callback stopped sounding like some special JavaScript concept.

It was just a function being passed into another function so it could be called later.

Sometimes understanding something is really just removing the fancy name from it.

Destructuring finally stopped feeling like magic

I’ve used destructuring plenty of times before:

const { name, role } = user;
Enter fullscreen mode Exit fullscreen mode

and:

const [firstUser, secondUser] = users;
Enter fullscreen mode Exit fullscreen mode

But during the refresher, I actually made a mistake and tried to destructure an array using {}.

That was useful.

It forced me to think about what JavaScript was actually doing.

Objects:

const { name, role } = user;
Enter fullscreen mode Exit fullscreen mode

Arrays:

const [firstUser, secondUser] = users;
Enter fullscreen mode Exit fullscreen mode

Objects are matched by property name.

Arrays are matched by position.

That mistake probably taught me more than just reading the correct syntax would have.

Spread and rest made more sense this time

Then came spread:

const updatedUsers = [...users, "Efo"];
Enter fullscreen mode Exit fullscreen mode

and:

const updatedUser = {
    ...user,
    role: "admin"
};
Enter fullscreen mode Exit fullscreen mode

I’d seen this syntax countless times before.

But revisiting it properly made the logic much clearer.

Spread takes existing values and spreads them into a new structure.

Rest uses the same ... but collects values:

function addUsers(...users) {
    return users;
}
Enter fullscreen mode Exit fullscreen mode

The way I remember it now is:

Spread = spread things out

Rest = gather things together
Enter fullscreen mode Exit fullscreen mode

Simple, but it works.

Async JavaScript was probably the most important part

Promises and async/await were where the refresher became much more valuable.

I created a Promise like this:

const getUsers = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve([
            { name: "Sabi", role: "admin" },
            { name: "Kong", role: "member" }
        ]);
    }, 5000);
});
Enter fullscreen mode Exit fullscreen mode

Then worked with .then():

getUsers
    .then((users) => {
        return users.filter(
            (user) => user.role === "member"
        );
    })
    .then((members) => {
        return members.map(
            (member) => member.name
        );
    })
    .then((names) => {
        console.log(names);
    });
Enter fullscreen mode Exit fullscreen mode

One thing that stood out here was the difference between logging and returning.

This:

console.log(users);
Enter fullscreen mode Exit fullscreen mode

shows me something.

This:

return users;
Enter fullscreen mode Exit fullscreen mode

passes the value forward so another part of the program can use it.

I knew that already in isolation, but Promise chaining made the difference feel much more important.

async/await made everything easier to reason about

Once I moved from .then() to:

async function showUsers() {
    try {
        const users = await getUsers;

        const members = users.filter(
            (user) => user.role === "member"
        );

        const names = members.map(
            (member) => member.name
        );

        console.log(names);
    } catch (error) {
        console.log(error.message);
    }
}
Enter fullscreen mode Exit fullscreen mode

the flow became much easier to read.

I also finally got a stronger understanding of what await actually does.

It pauses the current async function.

It does not pause the entire JavaScript program.

That distinction made async code feel a lot less mysterious.

Fetch tied everything together

Then I moved into fetch().

const response = await fetch(
    "https://jsonplaceholder.typicode.com/users"
);

if (!response.ok) {
    throw new Error("Failed to fetch users");
}

const users = await response.json();
Enter fullscreen mode Exit fullscreen mode

This was probably the point where the refresher stopped feeling like a list of separate JavaScript topics.

Suddenly everything connected:

functions
↓
Promises
↓
async/await
↓
HTTP
↓
fetch
↓
JSON
↓
arrays
↓
map / filter / find
Enter fullscreen mode Exit fullscreen mode

That was one of the biggest things I took away from the whole process.

The concepts make much more sense when they stop being separate chapters and start working together.

Modules were a good place to finish

The final part of the refresher was modules.

I practised exporting functions:

export function findUser(users, name) {
    return users.find(
        (user) => user.name === name
    );
}

export function getAdmins(users) {
    return users.filter(
        (user) => user.role === "admin"
    );
}
Enter fullscreen mode Exit fullscreen mode

and importing them somewhere else:

import {
    findUser,
    getAdmins
} from "./users.js";
Enter fullscreen mode Exit fullscreen mode

I also revisited the difference between named exports and default exports.

Named:

export function findUser() {}
Enter fullscreen mode Exit fullscreen mode
import { findUser } from "./users.js";
Enter fullscreen mode Exit fullscreen mode

Default:

export default function UserProfile() {}
Enter fullscreen mode Exit fullscreen mode
import UserProfile from "./UserProfile.js";
Enter fullscreen mode Exit fullscreen mode

This is something I’ve seen constantly in modern JavaScript code, but going back to the fundamentals made it feel much less like framework magic.

The main thing I realised

The biggest takeaway from this refresher wasn’t any one JavaScript feature.

It was realising how easy it is to confuse familiarity with understanding.

You can see something a hundred times and still have gaps.

You can recognise code without being able to write it confidently.

You can use a pattern without fully understanding why it works.

That was the whole reason I went back.

Not to become a JavaScript expert before moving on.

Just to make the foundation stronger.

And somewhere along the way, I started enjoying the process more than I expected.

There’s a different kind of confidence that comes from understanding the basics properly.

Not the confidence of knowing everything.

Just the confidence of knowing what you’re standing on.

So far I’ve revisited:

  • variables and data types
  • operators and conditionals
  • functions and scope
  • arrays and loops
  • map, filter, find, some, every and reduce
  • objects
  • destructuring
  • spread and rest
  • callbacks
  • error handling
  • Promises
  • async/await
  • HTTP and fetch
  • modules

And I actually feel better for slowing down.

Next for me is TypeScript.

But this time, I’m moving forward with a much clearer understanding of the JavaScript underneath it.

Sometimes going back isn’t really going backwards.

Sometimes it’s just the fastest way to stop building on shaky ground.

Top comments (0)