JavaScript at Breakneck Speed
The Super-Fast JavaScript Refresher Drills
Introduction
Cramming for an upcoming interview or coming back to front-end work after a long spell elsewhere?
You’ve come to the right place!
Each section of this article consists of a ‘drill’ that explores frequently-used JavaScript operations, as well as interesting nuiances of the language.
Names of variables and methods are kept deliberately short to minimize the amount of typing required to complete the code exercises.
What This Article Is Not
This article is about learning by doing and doesn’t offer thorough explanations of the operations used. You’re left to explore these operations in more detail on your own.
Setup
Browser
In Google Chrome, open the Developer Tools and run JavaScript directly in the console:
Repl
Here, I’ve created a Node.js environment with no need to install anything. You can either type your code on the left-hand side and run it, or execute it directly from the terminal on the right-hand side.
I’ve created a method ‘o’ that saves the need to write console.log(…) repeatedly:
Download and Install Node.js
If you prefer to work with your local environment, install Node.js :
Next, open the terminal, type ‘node’, and hit ENTER. Then, execute your JavaScript code. Executing JavaScript this way is much faster for exploring fundamental operations since printing to the console is taken care of:
If you prefer to work with files in an IDE, use an editor such as VS Code :
Code Results
I display the expected output on the right-hand side with a comment. For example:
Number.isInteger(1) // true
For operations that throw exceptions, I use the 🔥 emoji. For example:
Math.PI.toPrecision(0) // 🔥
Let’s get started!
Strings
Throughout this drill, we’ll be using the following constant strings:
const s = ‘Abc’
const t = ‘ def ‘
Case and Length
s // ‘Abc’
s.toLowerCase() // ‘abc’
s.toUpperCase() // ‘ABC’
s.length // 3
Extract Characters
s[0] // ‘A’
s[s.length 1] // ‘c’
s[3] // undefined
s[-1] // undefined
s.substring(0,2) // ‘Ab’
s.substring(2) // ‘c’
s.substring(3) // ‘’
s.substring(-1) // ‘Abc’
s.substring(-3) // ‘Abc’
Concatenation and Interpolation
s + t // ‘Abc def ‘
`s: ${s}` // ‘s: Abc’
`s: ${s}
t: ${t}` // ‘s: Abc
// t: def ‘
Remove Whitespace
t.trimStart() // ‘def ‘
t.trimEnd() // ‘ def’
t.trim() // ‘def’
Check the Start and End Characters of String
s.startsWith(‘A’) // true
s.startsWith(‘a’) // false
s.endsWith(‘c’) // true
s.endsWith(‘x’) // false
Extracting Parts of Strings
s.slice(0) // ‘Abc’
s.slice(1) // ‘bc’
s.slice(2) // ‘c’
s.slice(3) // ‘’
s.slice(0,1) // ‘A’
s.slice(0,2) // ‘Ab’
s.slice(1,2) // ‘b’
s.slice(1,3) // ‘bc’
s.slice(1,4) // ‘bc’
s.slice(-1) // ‘c’
s.slice(-2) // ‘bc’
s.slice(-3) // ‘Abc’
s.slice(-2,-1) // ‘b’
s.slice(-3,-2) // ‘A’
s.slice(-3,-1) // ‘Ab’
s.slice(2,1) // ‘’
s.slice(-2,-3) // ‘’
Stringify
String(true) // ‘true’
String(null) // ‘null’
String(undefined) // ‘undefined’
Compare Strings
‘1’ < ‘2’ // true
‘2’ < ‘1’ // false
‘a’ < ‘b’ // true
‘b’ < ‘a’ // false
‘A’ < ‘b’ // true
‘a’ < ‘B’ // false
‘A’ < ‘B’ // true
Includes
s.includes(‘A’) // true
s.includes(‘a’) // false
Finding the Index
s.indexOf(‘A’) // 0
s.indexOf(‘a’) // 1
s.match(/A/g) // [‘A’]
s.match(/a/g) // nullconst u = s.repeat(2)u.indexOf(‘A’) // 0
u.lastIndexOf(‘A’) // 3
u.indexOf(‘A’, 0) // 0
u.indexOf(‘A’, 1) // 3
u.indexOf(‘A’, 2) // 3
u.indexOf(‘A’, 3) // 3
u.indexOf(‘A’, 4) // 0
u.match(/A/g) // [‘A’,’A’]
Numbers
Drill Throughout this drill, we’ll be using the following constant numbers and strings:
const a = 2
const b = ‘3’
const c = Math.PI
const d = 123.456
Arithmetic
a + 3 // 5
a 3 // 1
a * 2 // 4
a * 1.25 // 2.5
a / 2 // 1
a / 3 // 0.6666666666666666
a % 2 // 0
a % 3 // 2
a ** 2 // 4
a ** 1.5 // 2.82842712474619
Number to String
d.toString() // ‘123.456’
`d: ${d}` // ‘d: 123.456’
null.toString() // 🔥
undefined.toString() // 🔥
String to Number
Number.parseInt(a) // 2
Number.parseInt(d) // 123
Number.parseInt(a, 10) // 2
Number.parseInt(null) // NaN
Number.parseInt(undefined) // NaN
Number.parseFloat(a) // 2
Number.parseFloat(d) // 123.456
Number.parseFloat(null) // NaN
Number.parseFloat(undefined) // NaN
String Concatenation Instead of Arithmetic Operation
a + b // ‘23’
a + parseInt(b) // 5
Convert Number to String and Round by Decimal Places
c.toFixed() // ‘3’
c.toFixed(0) // ‘3’
c.toFixed(1) // ‘3.1’
c.toFixed(2) // ‘3.14’
c.toFixed(3) // ‘3.142’
d.toFixed() // ‘123’
d.toFixed(0) // ‘123’
d.toFixed(1) // ‘123.5’
d.toFixed(2) // ‘123.46’
d.toFixed(3) // ‘123.456’
d.toFixed(null) // ‘123’
d.toFixed(undefined) // ‘123’
d.toFixed(-1) // 🔥
Convert Number to String and Round by Significant Figures
a.toPrecision(1) // ‘2’
a.toPrecision(4) // ‘2.000’
c.toPrecision() // ‘3.141592653589793’
c.toPrecision(0) // 🔥
c.toPrecision(1) // ‘3’
c.toPrecision(2) // ‘3.1’
c.toPrecision(3) // ‘3.14’
d.toPrecision() // ‘123.456’
d.toPrecision(0) // 🔥
d.toPrecision(1) // ‘1e+2’
d.toPrecision(2) // ‘1.2e+2’
d.toPrecision(3) // ‘123’
d.toPrecision(undefined) // ‘123.456’
d.toPrecision(null) // 🔥
d.toPrecision(-1) // 🔥
Exponentials
c.toExponential(0) // ‘3e+0’
c.toExponential(1) // ‘3.1e+0’
c.toExponential(2) // ‘3.14e+0’
d.toExponential(0) // ‘1e+2’
d.toExponential(1) // ‘1.2e+2’
d.toExponential(2) // ‘1.23e+2’
d.toExponential(null) // ‘1e+2’
d.toExponential(undefined) // ‘1.23456e+2’
d.toExponential(-1) // 🔥
Round, Ceil, and Floor
Math.round(c) // 3
Math.floor(c) // 3
Math.ceil(c) // 4
Math.round(‘’) // 0
Math.round(‘2.5’) // 3
Math.round(‘a’) // NaN
Math.round(null) // 0
Math.floor(null) // 0
Math.ceil(null) // 0
Math.round(undefined) // NaN
Convert Number to String and Round by Significant Figures
a.toPrecision(1) // ‘2’
a.toPrecision(4) // ‘2.000’
c.toPrecision() // ‘3.141592653589793’
c.toPrecision(0) // 🔥
c.toPrecision(1) // ‘3’
c.toPrecision(2) // ‘3.1’
c.toPrecision(3) // ‘3.14’
d.toPrecision() // ‘123.456’
d.toPrecision(0) // 🔥
d.toPrecision(1) // ‘1e+2’
d.toPrecision(2) // ‘1.2e+2’
d.toPrecision(3) // ‘123’
d.toPrecision(undefined) // ‘123.456’
d.toPrecision(null) // 🔥
d.toPrecision(-1) // 🔥 Exponentials
c.toExponential(0) // ‘3e+0’
c.toExponential(1) // ‘3.1e+0’
c.toExponential(2) // ‘3.14e+0’
d.toExponential(0) // ‘1e+2’
d.toExponential(1) // ‘1.2e+2’
d.toExponential(2) // ‘1.23e+2’
d.toExponential(null) // ‘1e+2’
d.toExponential(undefined) // ‘1.23456e+2’
d.toExponential(-1) // 🔥
Round, Ceil, and Floor
Math.round(c) // 3
Math.floor(c) // 3
Math.ceil(c) // 4
Math.round(‘’) // 0
Math.round(‘2.5’) // 3
Math.round(‘a’) // NaN
Math.round(null) // 0
Math.floor(null) // 0
Math.ceil(null) // 0
Math.round(undefined) // NaN
Math.floor(undefined) // NaN
Math.ceil(undefined) // NaN
The Number Class
Number(true) // 1
Number(false) // 0
Number(null) // 0
Number(undefined) // NaN
Number(b) // 3
Number(d) // 123.456
Number(` ${a} `) // 2
Number(‘1,2’) // NaN
Number(‘1 2’) // NaN
Number(‘a’) // NaN
Checking a Number is an Integer
Number.isInteger(1) // true
Number.isInteger(2.5) // false
Number.isInteger(‘1’) // false
Number.isInteger(null) // false
Number.isInteger(undefined) // false
Large and Small Numbers
Number.MAX_VALUE // 1.7976931348623157e+308
Number.MIN_VALUE // 5e-324
Number.POSITIVE_INFINITY // Infinity
1/0 // Infinity
Number.NEGATIVE_INFINITY // Infinity
1/0 // Infinity
Boolean
Standard vs. Strict Equality
2 == '2' // true
2 === '2' // false
'' == 0 // true
'' === 0 // false
1 == true // true
1 === true // false
0 == false // true
0 === false // false
null == undefined // true
null === undefined // false
Object Reference Equality
class Book {
constructor(title) {
this.title = title
}
}
const book1 = new Book('Drills in JavaScript')
const book2 = new Book('Drills in JavaScript')
book1 == book1 // true
book1 === book1 // true
book1 == book2 // false
book1 === book2 // false
const book3 = book1
book1 == book3 // true
book1 === book3 // true
String to Boolean
Boolean('test') // true
Boolean('true') // true
Boolean('false') // true
Boolean('') // false
Number to Boolean
Boolean(2) // true
Boolean(0) // false
Boolean(-1) // true
Array to Boolean
Boolean(['a']) // true
Boolean([]) // true
Object to Boolean
Boolean({}) // true
Boolean(null) // false
Boolean(undefined) // false
Recap of Truthy & Falsy
const j = (x) => x ? true : falsej(1); // true
j([]); // true
j('1'); // true
j(true); // true
j({}); // truej(0) // false
j(NaN) // false
j('') // false
j(false) // false
j(null) // false
j(undefined) // false
Functions
In this drill, we explore Javascript functions and cover control-flow, iteration basics, switch statements, and handling errors, with several examples given below.
Arithmetic
let a = (x,y) => { return x + y }
let b = (x,y) => { return x - y }
let c = (x,y) => { return x * y }
let d = (x,y) => { return x / y }a(2,3) // 5
b(2,3) // -1
c(2,3) // 6
d(2,3) // 0.6666666666666666
Summation with forEach
const n = [1,2,3]
let x = 0
n.forEach(function(y){
x += y
})x // 6
Control Flow Basics
const f = x => {
if (x === 2) {
return 'a'
} else if (x === 1) {
return 'b'
} else {
return 'c'
}
}f(2) // 'a'
f(1) // 'b'
f(0) // 'c'
Control Flow with Switch
function f(x) {
switch(x) {
case 1:
return 'a'
case 0:
return 'b'
default:
return 'c'
}
}f(1) // 'a'
f(0) // 'b'
f(-1) // 'c'
Switch with Multiple Values to Check
function f(x,y) {
switch(true) {
case x * y > 4:
return 'a'
break
case x * y > 2:
return 'b'
break
default:
return 'c'
}
}f(2,3) // 'a'
f(2,2) // 'b'
f(1,0) // 'c'
Checking for Null Parameters
function f(x,y) {
if (y) {
console.log(`x: ${x}, y: ${y}`)
} else {
console.log(`x: ${x}`)
}
}f('a','b') // 'x: a, y: b'
f('a') // 'x: a'
Arrow Functions
let f = x => x >= 0
f(3) // true
f(-1) // falselet g = (x,y) => x / y
g(8,2) // 4
g(1,3) // 0.3333333333333333
Terinary Operator
const f = x => (x < 10) ? true : falsef(5) // true
f(15) // false
Try-Catch on Code Block
function f() {
try {
throw 'e'
} catch (e) {
console.log(e)
}
}f() // 'e'
Simulating a Function Call that Sometimes Fails
const f = (x) => {
try {
g()
}
catch(e) {
console.log(`${x} failed: ${e}`)
}
}function g() {
var x = Math.random() <= 0.1
if (x) {
throw 'error'
}
}for (let i = 0; i < 10; i++) {
f(i);
}
// 2 failed: error
// 8 failed: error
Stringify
function f() { return true }String(f) // 'function f() { return true }'
Arrays
In this drill, we’ll cover iterating through and manipulating array values and some valuable methods to perform filtering operations and check conditions are satisfied. We’ll also use Javascript’s spread operator to combine two arrays, split strings into arrays, and merge array elements into strings.
Let’s begin by defining variables we’ll revisit throughout this drill to memorize array operations:
const m = ['a','b','c','d']
const n = [1,2,3]
const s = 'A;b;c'
Access the Array
m // ['a','b','c','d']
m.length // 4
m[0] // 'a'
m[1] // 'b'
m[4] // undefined
m[m.length - 1] // 'd'
m[m.length - 2] // 'c'
Remove Items
m.pop() // 'd'
m // ['a','b','c']
m.splice(2,99) // ['c']
m // ['a','b']
m.shift() // 'a'
m // ['b']
Add Items
m.push('e') // 2
m // ['b','e']
m.unshift('g','h') // 4
m // ['g','h','b','e']
Clear the Array
m.length = 0
m // []
The Spread Operator
const f = (x) => [...x]f('c') // ['c']
f('ab') // ['a','b']
Deconstructing an Array
const y = ['a', 1]
const [a, b] = ya // 'a'
b // 1
Merge Arrays with the Spread Operator
const a = ['a']
const b = ['b']
const c = [...'ab'][...a, ...b] // ['a','b']
c // ['a','b']
Find the Average Number using ForEach
function f(m){
let x = 0
m.forEach(y => {
x += y
})
return Math.round(x / m.length)
}f([1,2,3]) // 2
Find Index of an Entry
const f = (x) => x === 2
const g = (x) => x === 5n.findIndex(f) // 1
n.findIndex(g) // -1
Filter Entries
n.filter(x => x > 1) // [2,3]
n.filter(x => x < 1) // []
Find a Matching Entry
n.find(x => x === 1) // 1
n.find(x => x === 0) // undefined
n.find(x => x > 0) // 1
n.find(x => x > 1) // 2
Reverse Elements
n.reverse() // [3,2,1]
Check if Conditions Satisfied
n.every(x => x > 0) // true
n.every(x => x > 1) // false
n.includes(1) // true
n.includes(4) // false
Create an Array from Variable Number of Arguments
Array.of(1) // [1]
Array.of(1,2,3) // [1,2,3]
Split String into Array
'a,b,c'.split(',') // ['a','b','c']
'a,b,c'.split('.') // ['a,b,c']
Map
const t = s.split(';')
t.map(x => x.toUpperCase()) // ['A','B','C']
t.map(x => x.toLowerCase()) // ['a','b','c']
Reduce
const m = [2, 4, 2]
m.reduce((x, y) => x * y, 2) // 32
Joining Array Elements Into a String
n.join('|') // 1|2|3
Concatenation with forEach
const f = x => {
let s = ''
x.forEach((y) => {
s += `${y} `
})
return s
}f([1,2,3]) // '1 2 3'
Stringify Arrays
String(n) // '1,2,3'
String([['a','b'],n]) // 'a,b,1,2,3'
Math Library
The JavaScript built-in Math object contains constants and methods that allow you to carry out numerical operations. All properties and methods are static.
Truncating Numbers
const trunc = (x) => Math.trunc(x)trunc(1) // 1
trunc(Math.PI) // 3
Round, Ceil, and Floor
Math.round(1.4) // 1
Math.round(1.5) // 2
Math.floor(1.9) // 1
Math.ceil(1.1) // 2
Math.round(null) // 0
Math.floor(null) // 0
Math.ceil(null) // 0
Powers, Roots, and Absolute Value
const abs = (x) => Math.abs(x)
const pow = (x,y) => Math.pow(x,y)
const sqrt = (x) => Math.sqrt(x)
const cbrt = (x) => Math.cbrt(x)
Working with Math Static Properties
const {PI} = Math
const pow = (x,y) => Math.pow(x,y)const area = (r) =>
(4 * PI * pow(r,2))
.toFixed(2)area(5) // '314.16'
Maximum and Minimum
const a = [-1,1,2]Math.min(...a) // -1
Math.max(...a) // 2
Math.min(-1,1,2) // -1
Math.max(-1,1,2) // 2
Sign
const s = (x) => Math.sign(x)s(2) // 1
s(-2) // -1
Exponential and Logarithm
const exp = (x) => Math.exp(x)
const log = (x) => Math.log(x)
const log10 = (x) => Math.log10(x)
const log2 = (x) => Math.log2(x)exp(1) // 2.718281828459045
log(Math.E) // 1
log10(10) // 1
log2(4) // 2
Random
const rand = () => Math.random()
const ceil = (x) => Math.ceil(x)
const tossCoin = () => ceil(rand() * 2)let heads = 0, tails = 0
for (let i = 0; i < 100; i++) {
const result = tossCoin()
if (result === 1) heads++
if (result === 2) tails++
}console.log(heads) // 52
console.log(tails) // 48
JSON
We can move convert from a Javascript object to JSON with the stringify method, and in the other direction using the parse method.
Convert JSON string to Javascript object
const x = JSON.parse(
"\{\"a\":\"1\",\"b\":\"2\",\"c\":{\"d\":\"3\"}}")x.a // '1'
x.b // '2'
x.c.d // '3'
Convert Javascript object to JSON string
const x = {
a: "1",
b: "2",
c: {
d: "3"
}
}JSON.stringify(x) // '{"a":"1","b":"2","c":{"d":"3"}}'
Iterating
const f = x => {
let s = ""
x.forEach((y) => {
s += `${y.a}:${y.b};`
})
return s;
}const x = { a:"1", b:"2" }
const y = { a:"3", b:"4" }f([x,y]) // '1:2;3:4;'
Classes and Objects
Throughout this drill, we’ll be re-using the following class, function and constant:
class A {
constructor(x,y) {
this.x = x
this.y = y
this.m = []
}
get p() {
return (this.x * this.y) > 10
} get q() {
return `x: ${this.x}, y: ${this.y}`
} r(x) {
this.m.push(x)
}
s(x) {
return this.m.includes(x)
}
}function B(x,y) {
this.x = x
this.y = y
}const c = {
p: 'a',
q: {
r: 1,
s: 2
}
}
Checking for Equality
1 == '1'; // true
1 == [1]; // true
'1' == [1]; // true
1 === '1'; // false
1 === [1]; // false
'1' === [1]; // false
Accessing Values
c.p; // 'a'
c.q.r; // 1
c.q.s; // 2
Object.keys(c); // [ 'p','q' ]
Object.values(c); // ['a',{ r: 1,s: 2 }]
c['p']; // 'a'
c['q']; // { r: 1, s: 2 }
c['q']['r'] // 1
c['q']['s'] // 2
Combining Objects
const d = {
q: 'c'
};console.log({ ...c, ...d }) // { p: 'a', q: 'c' }
Destructing Objects
const { p, q, r ='r' } = c;p; // 'a'
q; // { r: 1, s: 2 }
r; // 'r'
Class Instances
const a1 = new A(1,2)
const a2 = new A(3,4)a1.x // 1
a1.y // 2
a2.x // 3
a2.y // 4
a1.p // false
a2.p // true
a1.q // x: 1, y: 2
a2.q // x: 3, y: 4
a1.s(1) // true
a1.s(3) // false
Inheritance
B.prototype.r = function() {
return `x: ${this.x}, y: ${this.y}`
}b = new B(1,2)
b.r() // x: 1, y: 2class E extends B {
r() { return 'r'; };
s() { return 3; };
}const e = new E();
e.r() // 'r'
e.s() // 3
Setting Object Properties
const f = (x) => {
x.find(z => z.a === 2).b = true
return x
}const x = [{
a: 1,
b: true
}, {
a: 2,
b: false
}]f(x) // [
// { a: 1, b: true },
// { a: 2, b: true }
// ]
Printing Object Property Values
const f = (x) => {
let s = x.map(z => z.a)
return s.join(' ')
}const x = [{
a: 1,
b: true
}, {
a: 2,
b: false
}]f(x) // '1 2'const h = (x, z) => {
const y = {
"a": `1 ${x}`,
"b": `2 ${x}`
}
return y[z.p]
}const a = {
p: 'a'
}const b = {
p: 'b'
}h('a', a) // '1 a'
h('b', b) // '2 b'const i = x => {
const y = {
1: "a",
2: "b"
}
return y[x] || 'error'
}i(1) // 'a'
i(2) // 'b'
i(3) // 'error'const array = []typeof array === 'object' // true
array.constructor === Array // true
Object.prototype.toString.apply(array)
=== '[object Array]' // true
Not a Number
typeof NaN === 'number' // true
NaN === NaN // false
NaN !== NaN // true
isNaN(NaN) // true
Sorting and Array of Objects
const m = [
{ 'a': 't', 'b': 2 },
{ 'a': 'r', 'b': 1 },
{ 'a': 's', 'b': 3 }
]const k = function(x) {
return function(y, z) {
if (!y
|| !z
|| typeof y !== 'object'
|| typeof z !== 'object') return const a = y[x], b = z[x]
if (a === b) return 0
if (typeof a === typeof b) return a < b ? -1 : 1
return typeof a < typeof b ? -1 : 1
}
}m.sort(k('a')) // [
// { a: 'r', b: 1 },
// { a: 's', b: 3 },
// { a: 't', b: 2 }
// ]m.sort(k('b')) // [
// { a: 'r', b: 1 },
// { a: 't', b: 2 },
// { a: 's', b: 3 }
// ]
Checking Object Contains a Property
const x = { a: 1 }
const y = Object.create(x)x.hasOwnProperty('a') // true
y.hasOwnProperty('a') // false
x.a // 1
y.a // 1
Thanks for reading! Let me know what you think in the comments section below, and don’t forget to subscribe 👍