Joshua's Docs - General JavaScript Misc. Notes

This page covers lots of JS tidbits that I'm having trouble categorizing under other pages. Things on this page might frequently shift around or get moved to other pages.

Forgetful JS

These are things that, for whatever reason, have a hard time sticking in my head. I'm hoping that summarizing some of them and writing them down will help me remember!

Object Destructuring

There are all kinds of destructuring in JS - check out MDN for details. There are lots of advanced ways to use them, but I would argue that some of the more advanced uses sacrifice readability and simplicity for not much gain in terms of reducing boilerplate.

Function Argument Destructuring

A common one I forget is available is destructuring of function arguments within the signature itself. I'll give you an example:

// This:
function talkToPets(shelter) {
	const {cats, dogs, birds} = shelter;
	// Or even more verbose, without destructuring at all
	//	const cats = shelter.cats
	//	const dogs = shelter.dogs
	//	const birds = shelter.birds

// Becomes this:
function talkToPets({cats, dogs, birds}) {

You can even define defaults!

function talkToPets({cats = ['whiskers','felix'], dogs, birds}) {

Computed Property Names

Computed property names are an awesome new(er) feature (ES6), which reduce a lot of the standard boilerplate involved when trying to use a dynamic value as the key itself on an object. For example, pretend you want to store an action keyed by a timestamp. Without computed property names, you would have to use:

const nowStamp = (new Date()).getTime();
const actions = {};
actions[nowStamp] = 'User logged in';

Using computed properties, you can use the variable directly as the key:

const nowStamp = (new Date()).getTime();
const actions = {[nowStamp]: 'User logged in'}

Or, even more succinct

const actions = {[(new Date()).getTime()]: 'User logged in'}

Computed Property Trick: Variable name as key

If you want to construct an object, where the keys are the actual variable names, and the values are the values, perhaps for logging, this is easy to do with Computer Properties, + ES6 Shorthand Property Names.

var dog = {
	name: 'barky',
	age: 5
var cat = {
	name: 'whiskers',
	age: 8
console.log({dog, cat});
{dog: {…}, cat: {…}}
	dog: {name: "barky", age: 5}
	cat: {name: "whiskers", age: 8}

For the above, console.table([dog,cat]) might be even better, since dog and cat share the same keys.


String to buffer

In Node.js, this is pretty easy with built-ins:

const myBuff = Buffer.from(myString, 'utf8');

With Web APIs, there is a bit more setup (and the ecosystem is currently changing). Currently, the best way seems to be to use the TextEncoder API, which returns a buffer (specifically a Uint8Array):

const encoder = new TextEncoder();
const myBuff = encoder.encode(str);

Array methods

Why are these so hard to remember? I don't know. But hopefully these practical examples will help!

Here is a master table of methods, some of which will be broken down more further down the page. An even more complete list of methods can be found on MDN, here.

Method Use Signature
forEach Loop over an array and callback for each element myArr.forEach((element) => doAny(element) )

Full Signature:
myArr.forEach((element, index, myArr) => doAny(element))
map Create a new array from the output of a callback called on each element of the original const formattedArr = => return newElement)
filter Creates a new array from the elements of the source that passed a test. Key to remember: If you want to keep element, return true, if you want to discard, return false const filtered = myArr.filter((element) => true || false)

const filtered = myArr.filter((element, index, sourceArr) => true || false, thisArg?)
findIndex Find the index of the first element in the arr that passes your test function myArr.findIndex((element) => true || false)
push Add to end of array myArr.push(newElement)
unshift Add to start of array myArr.unshift(newElement)
pop Remove from end const removedEnd = myArr.pop()
shift Remove from start const removedStart = myArr.shift()
indexOf Get the index of thing const found = myArr.indexOf(searchVal)

Will be -1 if not found.
splice Remove by index const removed = myArr.splice(startIndex, deleteCount)

Does modify original array in place.

Elements can be inserted in place of those removed, by passing as final args.
slice Returns a copy of a subsection of the original array const mySlice = myArr.slice(startIndex, endIndex)

Does not modify original array

Element at endIndex is not included in extracted.

This is a great way to quickly create a clone of an array - use without arguments:
const clone = myArr.slice()
join Join elements of an array const joined = myArr.join(separator)
concat Join multiple arrays together const combined = myArr.concat(myArrBeta)
reverse Reverse the order myArr.reverse()
sort Sort the array myArr.sort((firstElem, secondElem) => (+ || - || same))

Also, see subsection below
reduce Reduces an array to a single element output myArr.reduce((runningValue, currentValue) => newRunningValue)

Also, see subsection below
some Tests that at least one element of array satisfies test const result = myArr.some(testFunc)

const result = myArr.some((elem,index,fullArr)=> true || false, thisArg?)

For each of the samples, this will be the raw starting array:

const users = [{
	"id": 25,
	"name": "Amata Pittet",
	"email": "",
	"age": 32,
	"num_pets": 1,
	"notification_opt_out": false
}, {
	"id": 10,
	"name": "Tessi Maddy",
	"email": "",
	"age": 29,
	"num_pets": 2,
	"notification_opt_out": true
}, {
	"id": 3,
	"name": "Gillan Birkby",
	"email": "",
	"age": 50,
	"num_pets": 0,
	"notification_opt_out": true

Creating an Array

  • If the "thing" is iterable, or array-like, you can use Array.from()
  • For a regular object, you can use...

    • For values:

      • Object.values(object);
    • For keys:

      • Object.keys(object);
    • Both ({alpha: 1, beta: 2} => [{alpha: 1}, {beta: 2}])

      • Array.prototype.reduce is a decent approach:

        Object.keys(myObj).reduce((run, curr) => {
        		[curr]: myObj[curr]
        	return run;
        }, []);
        // Or, one liner:
        Object.keys(myObj).reduce((run, curr) => [, { [curr]: myObj[curr] }], []);
      • Warning: I've used [curr]: value to set the key to the value of a variable. This is an ES6 feature, called "computed property names"; for legacy support, you need to first create an object, then create key-pair normally (tempObj = {}; tempObj[curr] = myObj[key]);

  • For creating an array from scratch, prefilled with a value:

    • Use const myArr = Array(n).fill(val)

      • Where n = size of array, and val is value to fill with
      • If you want val to be the return value of some function, myFunction, you could use:

        • Array(n).fill(0).map(myFunction)
    • Relevant S/O

Array Splice vs Slice

If you are having trouble remembering the difference between splice and slice, an easy way to remember is imagining you want to buy a piece of cake. You would ask for a slice, and would definitely not use the word splice.

Similarly, if you want part of an array, you use slice, and calling myArray.slice() to clone the entire array is analogous to buying an entire cake but buying it piece by piece.

For splice, a good analogy is old movie film reel editing, where you cut scenes out of a film by removing a section and then joining the ends where the gap has opened up.

Array Reduce

MDN: Array.prototype.reduce


  • Minimal: myArr.reduce((runningValue, currentValue) => newRunningValue)
  • Full: myArr.reduce((runningValue, currentValue, currIndex, sourceArr) => newRunningValue, initialValue)


  • At its simplest, reduce takes an array and reduces it to *one* thing.


  • Often used for summing:

    const totalPets = users.reduce((running, curr)=> curr.num_pets + running, 0)
    // > 3
    [0, 24, 20].reduce((run,curr) => run + curr) // 44
  • Map an array of objects to a dictionary object with sensible keys. In this example, the user's ID # will become the object key

    const usersById = users.reduce((running,curr) => {
    	running[] = curr;
    	return running;
    }, {});
    // Now we can do this:
    const gillian = usersById[3];
  • Creating aggregators:

    const averages = users.reduce((running, curr, index, srcArr) => {
    	const count = (index + 1);
    	const totalAge = ((running.totalAge || 0) + srcArr[index].age);
    	const totalPets = ((running.totalPets || 0) + srcArr[index].num_pets);
    	running['totalAge'] = totalAge;
    	running['totalPets'] = totalPets;
    	running['avgAge'] = totalAge / count;
    	running['avgPets'] = totalPets / count;
    	return running;
    }, {});
    delete averages.totalAge;
    delete averages.totalPets;
    // > {avgAge: 37, avgPets: 1}

Note: MDN and most sites use "accumulator" as the name of the first argument to reduce. This bothers me, as besides being overly specific, it implies that reduce is about summing or gathering values together, which is does not have to be. I much prefer to use variables like runningValue, which just implies that there is a value carried while reducing and is used for the output.

Array Sort

MDN: array.prototype.sort


  • myArr.sort((firstElem, secondElem) => ( - || + || 0))


  • Sorts the array based on comparison function / callback

Here is how your comparison function should return a value:

Element you want to come first / move forwards What you should return
firstElem < 0 ( - )
Neither (don't change position) 0
secondElem > 0 ( + )

Put another way, if you are going to sort numerically, here is how you would apply subtraction to sort:

Sort Direction Basis of comparison
Small -> Large firstElem - secondElem
Large -> Small secondElem - firstElem

For example, if we wanted to sort our users by age, from youngest to oldest, we could do this:

const youngToOldUsers = users.sort((userA, userB) => userA.age - userB.age);

But you can use it with more than just numerical comparison!

For example, what if we want to sort users so that everyone that has opted out of notifications comes before those who have not:

const optedOutFirst = users.sort((userA,userB) => userA.notification_opt_out === true ? -1 : 0);

Arrays - Dealing With Duplicates

Arrays - Removing Duplicates

The easiest way is to convert the array into a set, since those cannot contain duplicates (by design), and then convert back with the spread operator (...):

const uniques = [ Set(myArray)];

If all you want is the count, or something like that, you don't have to use spread to convert it back:

// Notice: we use `.size` instead of `.length`, since we are keeping it as a Set
const uniqueCount = (new Set(myArray)).size;

For a non-ES6 solution, there are a lot of other approaches you can use, including combining .filter() and .indexOf(), hash maps, or .reduce().

Some examples:

  • const uniques = myArr.filter((elem,pos,arr) => arr.indexOf(elem) == pos)

Arrays - Finding Duplicates

If you want to find the duplicates in an array, you can use some approaches that are very similar to those for removing duplicates. For example,

  • const getDupes = items => items.reduce((acc, v, i, arr) => arr.indexOf(v) !== i && acc.indexOf(v) === -1 ? acc.concat(v) : acc, []); (credit)

Loop Types

MDN main page:

Another resource -

Loop Signature Note
for for ([initialVal]; [executeIfCondition]; [finalExpression];) {...} Don't use const for variable assignment of initialVal - won't allow modification via ++, --, etc.

Prefer let or var
do...while do {[statement]} while ({condition}); Condition is evaluated after do block, and if true, starts another loop through
while while ([condition]) {[statement]} Condition is evaluated before statement is executed.

You can use break to exit statement early and stop loop. for ([variable] in [object]) {[statement]} Only iterates over enumerable properties, in a random order.

Unlike for loops, you can use const for assigment here (and probably should!).

Although works with arrays, not recommended due to random order.

In general, simple for, or for...of is recommended over Unless you need to iterate over object keys of course.
for...of for ([variable] of [iterableObject]) {[statement]} Loop over *iterable objects*.

Using let vs const depends on how you use var in statement - use let if reassigning / modifying.
[].forEach myArr.forEach((element) => doAny(element) )

Full Signature:
myArr.forEach((element, index, myArr) => doAny(element))
Loop over an array and callback for each element

For Loops - Which to Pick?

In general, for...of is recommended as the go-to pick.

Compared to

  • It ignores non-iterable properties, does not.

Compared to forEach

  • for...of works on many different iterable objects
  • for...of is also generally faster
  • for...of allows exiting the loop early (via break), whereas forEach does not

The main remaining reason to use for() or [].forEach() is if you need access to the index. But this could also be accomplished with a counter, and most of the time is not needed anyways.

You can also combine with for ... of with object key iteration, by using something like for (const key of Object.keys(myObject)) {}

For In vs For Of

For which is better to use, see above (for of is usually better, if you can use it), but this section is for remembering how to use these methods.

Most important distinction:

  • for ... of loops over iterables, and returns the values

    • Objects = ❌
    • Arrays = ✔
  • for ... in loops over objects, and returns the enumerable properties (keys)

    • Objects = ✔
    • Arrays = ✔

If you can avoid using for ... in with objects, you should, and stick with Object.keys()


const testObj = {
	propA: 'hello',
	propB: 'world'
const testArr = ['hello', 'world'];

 * 👇 -- Using `for ... of` -- 👇
for (const val of testArr) {
	// > 'hello'
	// > 'world'

try {
	for (const val of testObj) {};
} catch (e) {
	// TypeError: testObj is not iterable

 * 👇 -- Using `for ... in` -- 👇
for (const prop in testArr) {
	// > 0
	// > 1
	// > 'hello'
	// > 'world'

for (const prop in testObj) {
	// > propA
	// > propB
	// > 'hello'
	// > 'world'

Special Loop Flow Controls


Console Methods

Method Use Signature
console.log Explodes your computer. JK! Logs to the console of course! console.log(thingToLog);

console.log(object_1, object_2?, object_3?, ...)

console.log(msgStr, substr_1?, substr_2?, ...) (string replacement)
console.assert Spit something out to the console only if your expression evaluates as falsy.

Kind of like wrapping logs in if statements -> if(!success) {console.log(result);} is close to console.assert(success, result)

console.assert(boolLikeAssertion, object_1, object_2?, object_3?, ...)

console.assert(boolLikeAssertion, msgStr, substr_1?, substr_2?, ...) (string replacement)
console.clear Clears the console console.clear()
console.count Increments and displays a counter value console.count(labelStr?)
console.countReset Resets the global counter, or a specific one if passed a label. console.countReset(labelStr?)
console.debug Logs at the debug level, which means it will only show for users with that level enabled. console.debug(thing)

Full signature matches console.log()
console.dir Displays a tree / interactive hierarchical display of an object, with collapsible sections.

Usually identical to just using log()
console.dirxml Same as console.dir() (shows hierarchical tree view), but for XML/HTML element.

Also usually identical to just using log()
'console.error' Logs error console.error(thing)

Full signature is same as log() Starts a group of messages in the console (kind of like a tree level)

Use console.groupCollapsed() if you want to start with it collapsed by default
console.groupEnd Ends a group of messages in the console (started by console.groupEnd() Logs at the info level. Identical to log() except for Firefox, which displays an icon.

Full signature matches console.log()
console.table Output a pretty formatted table, with auto headers and body.

Only helpful if all objects have same keys, logging a single object, or logging a multidimensional array where each sub-array has the same length
console.table([thing_1, thing_2, ...])

console.table([thing_1, thing_2, ...], [columnNameToOmit_1, ...])
console.time Start a timer, which can be checked later. (labelStr?)
console.timeEnd Stop a timer, and log the value. console.timeEnd(label?)
console.timeLog Log the value of a timer without stopping it console.timeLog(label?)
console.trace Output an (interactive) stack trace to the console. console.trace()

Or, pass any data (unlimited), and they will be logged just like console.log() --->
console.warn Logs at the warn level. console.warn(thing)

Full signature is same as log()

arg_name? <-- ? indicates argument is optional

Most browsers extend native Console methods with extra utilities; this docs page from the MS Edge documentation is an excellent overview that applies to many of the popular browsers, not just Edge.

  • For example, in both Firefox and Chromium browsers, you can use $ as an alias for document.querySelector, and $$ as an alias for document.querySelectorAll

Post vs Pre-increment

Most of the conversation around post vs pre-incrementing is about optimization and performance; but this is a bit of a moot point in a more abstracted / less bare metal language like JS anyways. But... there is something very important to remember: preincrement adds one to the value and then returns it, whereas postincrement returns the value first and then increments it last.

Why does this matter? Consider the following example, where we have a value that is either a number or undefined, and if undefined, we want to start it at 1:

var val = undefined;
val = val ? val++ : 1;
// > 1
// Good so far!
val = val ? val++ : 1;
// > 1
// Wait... val is not going up!

Because we are assigning the value of the return of a postincrementer to itself, and a postincrementer always returns the original value before incrementing it, the value is stuck at whatever was first fed into the postincrementer!

Now, with pre-incrementer:

var val = undefined;
val = val ? ++val : 1;
// > 1
// Good so far!
val = val ? ++val : 1;
// > 2
// Yeahoo!


The URL Web API has been around for a while now, and provides a much-need abstraction API for dealing with URLs.

For example, to access a query string parameter with requires some sort of pattern matching (e.g. RegEx) to extract the key pair you want, but with the URL API, it is as easy as (new URL(document.location)).searchParams.get(myParamKeyStr).

URL API Constructor

One of the main things to remember is that, in order to use the methods of URL(), you need to instantiate an instance of a URL object by calling the constructor.

The constructor can take:

  • A full URL - aka absolute URL

    • const myUrlObj = new URL('')
  • A relative URL, plus a base

    • const myUrlObj = new URL('/blog/?utm_source=cheatsheets', '')
  • Something that can be stringified to one of the above options

    • This is helpful to know, because it lets you use shorthand; if you want to construct a URL object from the current browser URL, you can use new URL(document.location) instead of new URL(document.location.href), since document.location.toString() returns the full href value anyway.

Why Use Object.defineProperty()?

Rather than just using myObj.prop = 'myVal, using the Object.defineProperty() method has some advantages:

  • You can control options:

    • configurable
    • enumerable
    • writeable
    • Etc.
  • These options in turn affect how the object can be consumed and modified

You can even declare an accessor descriptor, which lets you define a getter and setter function.

For more details, see the MDN page on the defineProperty.

Markdown Source Last Updated:
Thu Dec 03 2020 19:14:01 GMT+0000 (Coordinated Universal Time)
Markdown Source Created:
Wed Aug 21 2019 00:46:11 GMT+0000 (Coordinated Universal Time)
© 2021 Joshua Tzucker, Built with Gatsby