Skip to main content

JavaScript

Introduction

General

  • Just JavaScript • Fantastic, beginner-friendly deep dive that aims to correct mistakes in your mental model of how JS works • Dan Abramov & Maggie Appleton 📖

Variables

Functions

  • function keyword vs variable assignment:
    • one reason defining functions using the function keyword (instead of with variable assignment) can sometimes be preferable: the former are hoisted to the top of the file automatically so you can define them below the code that calls them if you want to
    • Sometimes I want to put helpers further down the file (like footnotes) so the main export can sit loud and proud at the top of a file
    • Can define anywhere in file, since hoisted (not necessarily above the line that uses it)
  • All optional aesthetics, though

Arrays

Filtering an array with an async callback

Loop n times

Array.from(Array(10).keys()).forEach(() => {
  createBookNode(createNode, { ...dummyBookNode, id: shortid.generate() })
  createAlbumNode(createNode, { ...dummyAlbumNode, id: shortid.generate() })
  createPodcastNode(createNode, { ...dummyPodcastNode, id: shortid.generate() })
})

or

Array.from({ length: 21 }, (_, i) => i * 0.05);

Generating an array of values that follow a pattern

  • e.g. Array.from({ length: 21 }, (_, i) => i * 0.05) generates an array of numbers from 0 to 1 in increments of 0.05
  • Array.from() • MDN 📚
  • generate an array of numbers • Stack Overflow 👨‍💻

Arrays & Objects

Objects

Referencing an object’s own properties

Simple way:

const obj = {
  a: value => value || obj.b,
  b:something
}
 
obj.a(true) // true
obj.a(false) // ‘something’

JS has late binding, so obj doesn’t need to be initialized before it is referenced. Be very careful with the way you leverage the power of lexical scoping of mutable references. In this case you are ok because of the use of const, but scary things can happen if you use let or something similar.

More involved way, but safer if not using const:

const createObj = () => {
  const b =something
 
  return {
    a: value => value || b,
    b: b
  }
}
 
const obj = createObj()
obj.a(true) // true
obj.a(false) // ‘something’

An inlined anonymous function is safer since it limits the number of locations that can mutate the obj reference.

Links:

Maps

Promises

Limiting a number between a minimum and maximum value

JSDoc

Debugging

  • Chrome Dev Tools:
    • Debugger:
    • Performance tab:
      • Use the Performance tab to record a page load and see what’s taking the most time:
        • Sort by “Self Time” to see which functions are taking the most time to run
          • “How to find your slowest lines of code using Chrome’s Performance tab”
        • Sort by “Network” to see which resources are taking the most time to load (true?)
  • Safari Dev Tools:
  • console.log:

Bun

maybeString ?? '' vs String(maybeString) vs maybeString.toString()

  • String(maybeString) — was my default, and works great for converting numbers and booleans to their string versions; but has the problem of turning null and undefined into the literal strings “null” and “undefined”. that’s never what i want
  • maybeString ?? '' — generally what I want for a string | null/undefined case; if null/undefined, give me an empty string so I’m still passing the expected type (a string)
  • maybeString.toString() - if you want to convert numbers, booleans, etc to strings, but throw an error on null/undefined instead of allowing a backup value (like an empty string)

Concurrency & Parallelism

Inbox