Learning to code with Javascript part 1

LC
10 min readJan 29, 2021

Started Launch School in the pandemic of 2020 and never looked back. Reached the end of JS 101. Here’s some scrappy notes turned into an even scrappier blog!

PEDAC

Solve any problem with PEDAC — your five step tool for taking on the world! Let’s break it down:

  • Step 1: Understanding the Problem
  • Step 2: Examples & Edge cases
  • Step 3: Determine your Datatypes
  • Step 4: Come up with an Algorithm
  • Step 5: Get Coding!

Explicit vs Implicit rules

  • Inputs, outputs, and rules (e.g. what is considered a word) are often stated explicitly, but some things you have to figure out… (e.g. which suffixes go with which numbers)

Edge cases, the big ones to remember

  • Capitalization, do I care?
  • What do I do with emptiness?
  • Testing inputs that are on the boundary! (e.g. if max array length is 20, test an array with length 20)
  • How do I handle duplicates?
  • How do I handle different data types?

What kind of questions should I ask?

  • Should I return a value, or print to console?
  • Do you want me to return the input or a copy of the input? (for mutable objects)

Data types

  • String uses: concat, reverse, regex, etc
  • Array uses: TO ITERATE. filter, map, reduce
  • Object uses: reference by key — look up, translate, digest
  • Number uses: MATH baby
  • Compound data structures: you know it when you see it?

Algorithm

  • Write it in the language of chosen data structure
  • Write out bigger picture algorithm, then go back and work on smaller steps
  • Start with two sentences, break down into subprocesses, THEN break down subprocesses

What’s up with formal pseudocode? It’s basically writing out the imperative code in english but with coding words. Here’s the language you should know:

  • START: start of the program
  • SET: set a variable that we can use for later
  • GET: retrieve input from user
  • PRINT: display output to user
  • READ: retrieve a value from a variable
  • IF/ELSE IF/ELSE: show conditional branches in logic
  • WHILE: show looping logic
  • END: end of the program
  • SUBPROCESS: step that hasn’t been broken down yet
  • # given: show input of program

What’s up with flow charts? Shows all the steps to your program in a visual way. Here are the shapes to use:

  • Start/Stop: Oval
  • Processing step: Rectangle (variable declarations, etc)
  • Input/Output: Parallelogram
  • Decision: Diamond (evaluating a conditional)
  • Connector: Circle (loop or conditional drop off point)

Debugging 101

Using stack trace

  • 1) Study the error message
  • 2) try to walk backward through the code to understand how the program flow arrived at the error.
  • 3) Think about all the data in use at the error location, and how missing or incorrect data might have caused the problem.
  • 4) Use a search engine to look up the error message.

Steps to debugging

  • Reproduce error
  • Determine bounds of error
  • Trace code / trap the error
  • Understand the problem
  • Implement a fix: FIX ONLY ONE PROBLEM AT A TIME

Techniques for debugging

  • Rubber duck
  • Line by Line
  • Walk away
  • Use a debugger (node inspect)

Learning the language

Operators & Operands

  • Logical operators = ||, &&, !
  • Arithmetic operators = +, -, /, *, **, %
  • Comparison Operators = >=, <=, ==, ===, !=, !==, <, >
  • Assignment Operators = +=, -=, *=, /=, %=, ==
  • typeof operator
  • conditional operator = ?
  • Operands = what’s being operated on

Objects vs Primitives

  • Primitives: string, number, boolean, null, undefined
  • Objects: objects, arrays, functions, etc.
  • Primitives are immutable, objects can be mutated. Primitives are pass-by-value, objects are pass-by-reference

Statements vs expressions

  • Statements = anything that performs an action (if statement, loops, variable declaration, function declaration)
  • Expressions = anything that evaluates to a value (a + b, variable assignment)
  • When JavaScript expects a statement you can also write an expression, but when JavaScript expects an expression you can’t write a statement.

Function Expressions vs Function Declarations

  • Function Expression example: let getRectArea = function(w, h) {w * h};
  • Function Declarations example: function calcRectArea(w, h) {w * h}
  • The main difference between a function expression and a function declaration is the function name, which can be omitted in function expressions to create anonymous functions.
  • Unlike function declarations, function expressions aren’t hoisted*.

*hoisting moves all declarations to the top of the current scope. This means that you can’t use function expressions before you create them.

Declarative vs Imperative Programing

  • Declarative syntax= using subprocesses to show logic without stepping every detail (e.g. higher order functions, telling the interpreter to do some function for us)
  • Imperative syntax= showing each step of the logic flow to a problem (e.g. for loop, telling the interpreter what to do each step of the way)

Selection vs Transformation

  • Selection = picking out only numbers that meet a condition (filter)
  • Transformation = manipulating every element in a collection (map)

Function scope vs block scope

  • Function scope = created for every function (and we can nest them)
  • Block scope = what you get when you use if statements, for statements, etc. You can also use them stand-alone with a simple begin-end curly braces {}, not to be confused with empty object literals or class definitions.
  • For both scopes, outer blocks cannot access variables from inner scopes; inner blocks can access variables from outer scopes; variables defined in an inner block can shadow* variables from outer scopes.

*shadow means that inner variable takes precedence within the local scope

First class vs higher order vs callback functions

  • First Class Function = functions that can be stored in a variable, object, or array; passed as an argument to a function; or returned from a function
  • Higher Order Function= function that takes other functions as arguments
  • Callback function = function that is passed into other functions as arguments
  • Here what you need to know with callback functions: what type of action is being performed (method, reference, callback execution), what the action is being performed on, side effects of action, return value, & where return value is used.

Let’s Code! A bunch of methods to know.

A list of String Methods

  • ‘’.split(delimiter) : returns array of strings split at delimiter
  • ‘’.search(regex): returns index of first match between regex and given string, or -1 if no match was found
  • ‘’.slice(startIndex, endIndex — non-inclusive): returns portion of string (or copy of string if startIndex is 0‘’)
  • ‘’.splice(startIndex, numberToRemove, replacement): removes characters and adds new chars in its place. returns new string.
  • ‘’.substring(startIndex, endIndex — non-inclusive): returns portion of string
  • ‘’.concat(string2, moreStrings): returns new string that concatenates strings (or copy of string2 if given string is ‘’)
  • ‘’.replace(searchValue, replacement): returns new string, with some or all matches of a pattern replaced by a replacement
  • Reference by index ‘Hello’[1]: returns ‘e’
  • ‘’.toString(): returns a string of object
  • ‘’.toUpperCase(): returns all-caps string
  • ‘’.toLowerCase(): returns all lower-case string
  • ‘’.includes(searchString): returns boolean if string contains searchString (also ‘’.endsWith(searchString) and ‘’.startsWith(searchString))
  • ‘’.trim(): removes white space around string (also .trimStart() and .trimEnd())
  • ‘’.indexOf(searchString): returns index of first occurance of searchString within string, or -1 if not found
  • ‘’.match(regex): returns array of all results matching the complete regex (if g is used) OR the first complete match (if g is not used), or null if no matches are found.
  • ‘’.padStart(targetLength, padString = ‘ ’) : returns string padded with padString until it reaches target length (also ‘’.padEnd)
  • ‘’.repeat(numberOfRepeats): returns new string containing given string repeated a bunch of times

What’s the difference between slice and substring?

  • ‘string’.slice(-3, -1) => ‘string’.slice(3, 5) : returns ‘in’
  • ‘string’.substring(-3, -1) => ‘string’.substring(0, 0) : returns ‘’
  • ‘string’.slice(4, 2) : returns ‘’
  • ‘string’.substring(4, 2) => ‘string’.substring(2, 4) : returns ‘ri’
  • ‘string’.slice(1, -2) => ‘string.slice(1, 4) : returns ‘tri’
  • ‘string’.substring(1, -2) => ‘string’.substring(0, 1) : returns ‘s’

A list of Array Methods

  • [].slice(startIndex, endIndex — non-inclusive): returns portion of array. non-destructive
  • [].splice(startIndex, numberToRemove, replacement): returns same array with elements removed and optional new elements in its place. DESTRUCTIVE
  • [].push(newElement, moreNewElements): returns same array but with new elements added to the end. DESTRUCTIVE
  • [].pop(): removes last element from array, and returns popped element. DESTRUCTIVE
  • [].shift(): removes first element from array, and returns removed element. DESTRUCTIVE
  • [].unshift(newElement, moreNewElements): returns same array but with new elements added to the front. DESTRUCTIVE
  • [].concat(newArray): returns new array that concatenates two arrays (or shallow copy of newArray if given array is []) Non-destructive
  • [].includes(searchElement): returns boolean if array contains searchElement
  • [].join(delimiter) : returns array elements joined into a string
  • [].sort((a, b) => sort order) : sort by callback function, returns sorted array (DESTRUCTIVE!)
  • [].reduce((acc, currentVal, index) => reduce function, accStartingValue) : returns reduced function (non-destructive)
  • [].forEach((element, index)=> callback function): does function, returns undefined (non-destructive)
  • [].filter(element => condition): returns array containing only elements that meet condition (non-destructive)
  • [].find(element => condition): returns first element to meet condition, or undefined if not
  • [].findIndex(element => condition): returns first index in the array with element that meets condition, or -1 if not found.
  • [].every(element => condition): returns boolean if every element meets condition
  • [].some(element => condition): returns boolean if at least one element meets condition
  • [].fill(fillElement, optnlStartIdx, optnlEndIdx): returns given array with start index to an end index filled with static value. DESTRUCTIVE
  • [].indexOf(searchElement, optnlStartIdx): returns first index at which a given element can be found in array, or -1 if it is not present
  • [].reverse(): reverses the order of the elements of an array in place. (First becomes the last, last becomes first.) DESTRUCTIVE
  • Array.isArray(array): returns boolean if object is an array

A list of Object Methods

  • Object.keys(obj1) : returns array of keys in object
  • Object.values(obj1): returns array of values of object
  • Object.entries(obj1): returns nested array of key value pairs [key, value]
  • Object.assign(target, source): copies all enumerable own properties from source objects to target object and returns target object. (or clones object if target is {})
  • {}.hasOwnProperty(searchKey): returns boolean if object contains searchKey
  • Object.freeze(obj1): returns given object frozen in place
  • Object.fromEntries(nestedArray): returns object from nested array of key value pairs
  • Object.is(data1, data2): returns boolean if two pieces of data are the same object
  • {}.toString(): returns string representation of object

Oh also…

  • Math.floor(), Math.ceil(), Math.round(). Math.random()

Wowza! That’s a lot of methods. What’s next?

Truthiness, Operators, and Coercion

What’s falsy? That’s a FUN ONE to answer (get it?)

  • false
  • undefined
  • null
  • 0
  • NaN
  • ‘’

What’s short-circuiting?

  • Logical expressions get evaluated left to right, and they will stop evaluating once a condition is met. (e.g. (true || ***) evaluates to true with no error, (false && ***) evaluates to false with no error)
  • When to use? Suppose you have a name variable that usually contains a string, but may sometimes contain null. Before you can use the string’s length property, you must confirm that it isn’t null, so you could say ‘if (name && (name.length > 0))’. If name was null, this would return false without throwing an error.

Precedence and Evaluation order (don’t depend on it!)

an operator that has a higher precedence than another is said to bind more tightly to its operands

Mathematical Operator Precedence

  • PEMDAS

Logical Operator Precedence

  • parentheses
  • <=, <, >, >= — Comparison
  • ==, != — Equality
  • && — Logical AND
  • || — Logical OR

Expression Evaluation Order

  • Left to right: Arithmetic evaluates functions/methods/values left to right, then moves on to calling operators/evaluating precedence
  • Right to left: ** operators (3 ** 3 ** 3) and multiple assignments go right to left (a = b = c = 3)

Implicit Type Coercion

  • JavaScript implicitly coerces interpolation expressions like ${something} to string values.
  • undefined == true
  • when number/object/boolean + string, everything is coerced to string
  • when number/object/boolean + object, everything coerced to string
  • when number/boolean/undefined/null + number/boolean/undefined/null, everything coerced to number (null + true = 1)
  • Using comparison operators (<, >, <=, >=, ==), JavaScript converts both operands to numbers before comparing them (unless they are both strings). Objects also converted to primitives when compared with primitives ({} coerced to [object Object], [] coerces to ‘’).

Explicit Type Coercion

  • Number() takes a string, converts it to a number if it can, then returns that number. If it can’t convert the string to a number, it returns the value NaN. Number() converts empty strings and strings with only whitespace to 0. Number() converts boolean to 0 or 1.
  • parseInt() and parseFloat() convert strings to numbers
  • - turns a number negative
  • + coerces value to a number
  • .toString() returns string representation of value, and can be used on all types except null and undefined. can’t be called directly on a number, so to wrap the number in parentheses to make it a number object (42).toString()
  • String() works just like .toString(), but it works on null and undefined. Sometimes leads to errors.

Other fun tidbits

Array Destructuring

  • let [catName, dogName] = [‘Lynxy’, ‘Marley’] assigns ‘Lynxy’ to catName and ‘Marley’ to dogName

Side effects

Functions have side effects if anything it does alters what happens elsewhere in the program. Possible side effects happen when the function:

  • reassign non-local variables
  • mutates the value of an object referenced outside of local scope
  • reads from or writes to a file, network connection, browser, or system hardware (including writing to the console log or reading input from terminal)
  • raises an exception
  • calls another function that has side effects
  • use _ for unused callback arguments

Coding tips & pitfalls

  • functions should be at the same level of abstraction
  • name things descriptively
  • avoid magic numbers
  • when naming functions, be clear about side effects vs return values
  • avoid printing AND returning
  • NEVER mutate the caller while iterating
  • try not to use destructive functions ever

Loop controls

Break

  • if you put break at the end of generic loop, it mimics behavior of do-while loop
  • if you put break at the beginning of generic loop, it mimics behavior of regular while loop
  • use generic loops if you want to break in the middle of a loop!

Continue and guard clauses

  • use continue to take certain elements in the loop out of contention in a super readable way (less nested logic)
  • Guard clauses always include a continue, break, or return statement in the body of the if, depending on need. Most shouldn’t do anything else, but that’s not a strict rule.

Why Arrays are quirky

  • Sparse means that length & number of elements in an array are different
  • You can add empty items by changing length. These are counted by length, but not used to iterate. Empty array items return undefined.

How does sorting work? Array.prototype.sort()

With no arguments, Array.prototype.sort() converts everything to string and sorts by unicode char, and undefined goes to end of array. Always make a copy before sorting.

UTF-16

  • Uppercase < lowercase
  • Digits and most punctuation < letters.
  • Some punctuation characters between uppercase and lowercase letters, and several after all of the letters.
  • Extended ASCII table with accented chars > the main ASCII table.
  • All other UTF-16 chars > the extended ASCII table (code point >= 256).

Sorting numbers.

[2, 11, 9, 4, 107, 21, 1].sort((a, b) => a — b);

  • If the callback (a - b) returns a number less than 0, place a before b.
  • If the callback (a - b)returns a number greater than 0, place b before a.
  • If the callback (a - b) returns 0, leave the relative positions of a and b unchanged.

When sorting string numbers (‘1’, ‘2’, etc), make sure to convert to numbers before sorting.

A quick guide to shallow copies because mutating without copies is just bad news

  • array.slice()
  • […array]
  • object.assign({}, obj2)

Whew. All done! There’s plenty I missed, but this is a good general overview. Good luck coding!

Unlisted

--

--