Blog Post

Beginner JavaScript (Wes Bos Course)

Back to all Posts
Post Info:


In mid-July 2022 I did a leveling and performance review exercise with my manager at work (which resulted in a raise / promotion for me 🤑). One of the objectives I set was to improve my understanding of JavaScript, which I use everyday at work. Technically we use Vue for our frontend applications, but we believe the underlying language is more appropriate than the framework it sits on top of. The process of the exercise spanned several weeks and so I came accross Beginner JavaScript by Wes Bos. And he put the entirety of the course in written form for FREE on his website. I decided a cadence of one lesson per-work day would work well for me and while "beginner" isn't my category I was confident I would learn something in almost every lesson, or at least a reminder. And to keep myself accountable I decided to make a Twitter thread of the takeaway from each lesson. You can find that thread here:

Additionally, we started a book club reading Eloquent Javascript, but I'll write about that later.

Day 1: Running and Loading JS

I Learned if you have a script tag that imports an external JS file you can't put any JS inside that tag and expect it to run. Example:

<script src="./some.js">
  console.log("Hey ma!"); // Won't print

Lesson Link

Day 2: Variables and Statements

"Kebab case" variables are not valid JavaScript Never realized this! Screenshot of error in the console that results from attempting to use kebab-cased variables. Lesson Link

Day 3: ESLint and Prettier

ESLint and Prettier. These are magic. ESLint: tells you why your code is not up to standard. This can be frustrating, but it helpful on projects to have a clear guidelines. Prettier: fixes syntax issues to keep code looking right. Lesson Link

Day 4: Intro to Types.

Symbol is a type in JS, that allows for unique identifiers for Objects. But I'm struggling to try to use it... I can add Symbols as keys, and get a list of keys, but I can't access the value with that Symbol. I need to learn more here. Lesson Link

Day 5: Numbers:

TIL that 0.1 + 0.2 = 0.30000000004 in most programming languages 🤯. Also that NaN is typeof number. Lesson Link

Day 6: Objects:

I feel good about my understanding here, always good to refresh though. I remember it being hard to understand why you would group things at first, but a person as an "Object" is a good example. Lesson Link

Day 7: Null and Undefined

TIL: You cannot have a const of undefined unless you explicitly set it as such. Because a const variable must be initialized with a value.

const cantBeUndefined;
// Uncaught SyntaxError: Missing initializer in const declaration
const canBeUndefinted = undefined;
// Works!

Lesson Link

Day 8: Booleans and Equality

"=== always checks that the value AND type are exactly the same." -Wes Bos (emphasis added). I remember getting tripped up by single, double, and triple = when I first started. Glad for the refresher here. Lesson Link

Day 9a: Built-in Functions

There are many built-in functions in JS. Some handle tedious work for us and return values (parsing numbers), others perform actions (scrollTo scrolls a user to a certain place) and don't return anything. Lesson Link

Day 9b: Custom Functions

Variables inside functions are temporary and after the function is run they are "garbage collected" (i.e. deleted from memory). If you want to use a value returned from a function, you need to save it in a new variable. Lesson Link

Day 10: Paramenters and Arguments

TIL: The difference between parameters and arguments. Parameters are in the function declaration, and arguments are passed when the function is called. But let's be real, they are used interchangeably. Lesson Link

Day 11: Different Ways to Declare Functions

TIL Methods are functions that live inside of objects! Code Example:

const person = {
    name: "Andy",
    sayHi() { console.log(`Hi ${}!`)},

sayHi() is a method! Lesson Link

Day 12: Debugging Tools

Console.table() is a Dream come true. HOW HAVE I NEVER KNOWN ABOUT THIS?! Console.count() will also be super useful. There are also way more ways to add breakpoints in the console than I knew about! Lesson Link

Day 13: Scope

All I can say is that scoping is hard. Lesson Link

Day 14: Hoisting

Most of this is pretty straightforward, but I found this quote helpful: "Only function declaration types of functions are hoisted, not function expressions (when you put a function in a variable)." Little gotcha there. Lesson Link

Day 15: Closures

Closures are functions that return a function. Those functions can then be run independently from then on and keep their data. Closures are useful if you need to do something more than once (like perhaps keep the score of two games going). Lesson Link

Day 16: Intro to the DOM

Window: Global, everything for your browser lives in here. Navigator: Browser specific, permissions, and your device. Document: All your HTML lives in here. This is your entry point to interacting with JavaScript. Lesson Link

Day 17: Selecting Elements

It is interesting that querySelectorAll() will select all the elements on the page no matter how deeply nested they are. So child elements with parents of the same type will be returned as separate items in the NodeList Lesson Link

Day 18: Element Properties and Methods

"...the difference between elements and nodes. Nodes can be anything, but an actual element is something that is wrapped in a tag." I learned about the insertAdjacentText() method! Lesson Link

Day 19: Working with Classes

Didn't learn anything specifically "new", but nice reminder of how to toggle classes on and off, and add event listeners to run functions. Lesson Link

Day 20: Built-in and Custom Data Attributes

TIL working with custom data-attributes on an element you use element.dataset to get access to its attributes. Example

<div class="name" data-name="Andy">Div</div>

I would use document.querySelector(".name") to get access to "Andy" in data-name attribute. Lesson Link

Day 21: Creating HTML.

Good reminders of the basics like document.createElement(), and element.appendChild(), but also some new ones I don't recall using like element.cloneNode() and document.insertAdjacentElement() Lesson Link

Day 22: HTML from Strings and XSS

I've never used document.createRange() and/or createContextualFragment(). I'd imagine many frameworks use these under the hood (or similar) to limit DOM re-rendering. Very cool! Lesson Link

Day 23: Traversing and Removing Nodes

The difference between element.children vs element.childNodes.

<div class="andy">Hi, my name is <em>Andy Pickle</em>. I like coffee, music and watches</div>
const andy = document.querySelector('.andy');

andy.children will show an HTMLCollection with only the <em> in it. Whereas andy.childNodes will show a NodeList with text, <em>, and more text. Essentially .childNodes gives you everything inside what you've selected and .children only gives you HTML elements inside your selection. Lesson Link

Day 24: Cardio

Challenge: take a blank JS file and edit an HTML file with it. But write all JavaScript out BEFORE looking at the results. My solutions had several errors, but I got there in the end. It was good to review insertAdjacentHTML().

Day 25: Event Listener

(paraphrasing Wes here) The three steps for event listeners:

  1. Get element
  2. Listen for an event
  3. Do something

Other learnings:

  1. Adding an event listener is called binding and removing one is called unbinding.
  2. You cannot unbind a listener that has been declared with an anonymous function.
// Adding a listener
element.addEventListener('click', function() {
// Attempting to remove it
element.removeEventListener('click', function() {
}) // Doesn't work

This doesn't work because even though the function is exactly the same, the listener needs to be a reference to a named function. If we ever want to remove a listener we need to declare its callback function with a name.

Lesson Link

Day 26 Targets, Bubbling, Propagation and Capture

event.pressure works on touchscreen devices!

The difference between and event.currentTarget is currentTarget is the specific element clicked, and target can be an event that has been bubbled up by a child element.

  function whoFiredTheEvent(event) {
    if( === event.currentTarget){
      console.log("Button Fired it")
    if( !== event.currentTarget){
      console.log("Child Span Fired it")
  const buttons = document.querySelectorAll('button');
  buttons.forEach((button) => {
    button.addEventListener('click', whoFiredTheEvent)
  <button class="no-bubbles">
    No Bubbles
  <button class="bubbles">
    Bubbles <span>Up</span>

In the example above if you click on "Up" you will see that the currentTarget is <span>Up</span> but the function whoFiredTheEvent is still called because it bubbles up. If you don't want an event to bubble up you can use event.stopPropagation(). You can also make sure to capture events in global way by using the third parameter to your eventListener. Like so:

window.addEventListener('click', (event) => {
  console.log('in the capture phase');
  { capture: true }  

If the above code was added to the previous example then we would never make it to the whoFiredTheEvent() function because the capture phase occurs before the bubbling phase. This could be helpful if you need to check for something BEFORE adding / removing a certain listener. But probably not on "click".

Lesson Link

Day 27 Prevent Default and Form Events

event.preventDefault() allows you to override the default behavior of a particular element. Links should take you somewhere, but adding event.preventDefault() allows you to do something first, or perhaps ask a second question. Its main usecase is on forms and buttons in my experience. Lesson Link