JS Algorithms And Data Structures Certification
Notes from following freeCodeCamp's JS algorithms and data structures cert.
Basic JavaScript
Check out the assortment of assignment operators. I typically only use
+=
and never think of using the rest!Characters in string are immutable. The strings themselves are not. So you can change the value of a whole string (
s = 'new value'
), you can read single characters with bracket notation (let t = s[2]
), but you cannot change a single character in an existing string (s[2] = 'a' // not!
).Become more fluent with array methods:
push
,pop
,shift
,unshift
,splice
,slice
,concat
,forEach
,indexOf
,lastIndexOf
,includes
,find
,findIndex
,filter
,map
,sort
,reverse
,split
,join
,reduce
,reduceRight
,isArray
.Assigning a value to an undeclared variable implicitly creates it as a global variable (it becomes a property of the global object) when the assignment is executed. The differences between declared and undeclared variables are:
Declared variables are constrained in the execution context in which they are declared. Undeclared variables are always global.
Declared variables are created before any code is executed. Undeclared variables do not exist until the code assigning to them is executed.
Declared variables are a non-configurable property of their execution context (function or global). Undeclared variables are configurable (e.g. can be deleted).
Study scopes.
Understand coercion and different behavior between
==
vs===
and!=
!==
.Review
switch
syntax and patterns.
ES6
It seems that
'use strict';
at the top of your files or the start of functions is recommended. It's rather annoying to have to write that every time, don't you think? Javascript.info has a good succinct article on how to use strict mode.I've also found some recommendations warning that if your code is processed by some build system (minification, concatenation...), you might have unexpected results when mixing strict and sloppy scripts. One solution is to
'use strict';
at the start of functions. Another problem to consider is that if your code is executed in older browsers, they might not support strict mode and you might get unexpected results as well. Preventing problems in this scenario would require careful testing.In JavaScript,
const
does not mean constant, but one-time assignment. But, the part that's constant is the reference to an object stored within the constant variable, not the object itself.javascriptconst settings = {baseUrl: 'https://example.com'};settings = {}; // fail!settings.baseUrl = 'https://evil.example.com'; // win!Declaring a variable to be constant doesn't make the objects it references immutable. Object properties can change or be deleted altogether. The same goes for arrays assigned to a constant variable; Elements can be added, removed, reordered, or modified.
To make an object truly immutable, you can pass it to the
Object.freeze
function to prevent any changes to its properties. Be aware that freeze is shallow, so you'll have to recursively call it for nested objects if you want the entire object tree to be frozen. If you need immutable data structures, it might be safer and more convenient to use a library such as Facebook's Immutable.js which is specifically made for this purpose.An arrow function expression is a syntactically compact alternative to a regular function expression, although without its own bindings to the this, arguments, super, or new.target keywords.
Arrow function expressions are ill suited as methods, and they cannot be used as constructors. Arrow functions are always anonymous. Two factors influenced the introduction of arrow functions: shorter functions and non-binding of this. An arrow function does not have its own
this
; thethis
value of the enclosing execution context is used.Functions that operate on other functions, either by taking them as arguments or by returning them, are called higher-order functions. Eloquent JavaScript has a great article on higher-order functions.
I always forget that I can declare function parameters with default values. Default function parameters allow named parameters to be initialized with default values if no value or
undefined
is passed:javascriptfunction multiply(a, b = 1) {return a * b;}I use destructuring assignment regularly, but I rarely reach out for new names and default values:
javascriptlet o = { p: 42, q: true };let { p, q } = o; // basiclet { p: foo, q: bar } = o; // new nameslet { q = false, r = 'hi' } = o; // default valueslet { p: foo = 1, q, r: bar = 'hi' } = o; // combinedI haven't written much code using classes in JavaScript. JavaScript classes, introduced in ECMAScript 2015, are primarily syntactical sugar over JavaScript's existing prototype-based inheritance. The class syntax does not introduce a new object-oriented inheritance model to JavaScript. JavaScript.info article on classes is quite good.
In summary, the basic class syntax looks like this:
javascriptclass MyClass {prop = value;constructor(...) {// ...}method(...) {}get something(...) {}set something(...) {}[Symbol.iterator]() {}// ...}MyClass
is technically a function. Methods are written toMyClass.prototype
.
Regular Expressions
Use regular expressions with many methods. Popular ones are:
str.match(regExp)
regExp.test(str)
str.replace(regExp, newStr|fun)
Match literals like this
/hello/
Provide alternatives like this
/yes|no|maybe/
Flags go at the end of the regular expression like this
/regex/flags
. The two most popular flags are:i
for case insensitive search andg
for global search..
matches any character except newline, but can be made to include newline with thes
flag.Use square brackets to define character sets:
/[abc]/
would be equivalent to/a|b|c/
, if I'm not mistaken. Use-
to define ranges. Use[^...]
to define a character set by specifying its complement. I.e.[^abc]
matches everything excepta
,b
orc
.For frequently used character sets, shorthand character classes exist. The most popular:
\w
equivalent to[A-Za-z0-9_]
and\W
its complement\d
equivalent to[0-9]
and\D
its complement\s
equivalent to[ \r\t\f\n\v]
and\S
its complement.
Quantifiers establish whether a given character or group can repeat itself:
?
0 or 1 times*
0 or more times+
1 or more times{n}
exactly n times{min,max}
a number of times in between min and max (inclusive). Either min or max can be omitted.
^
at the beginning of the regular expression denotes beginning of string.$
at the end denotes end of string.Lookaheads establish an extra condition without becoming part of the match. Positive lookahead
x(?=y)
matchesx
when followed byy
. Negative lookaheadx(?!y)
matchesx
when not followed byy
.Note that
^
and?
mean different things depending on where they're used.By default, regular expressions behave in a greedy manner. For example,
/t[a-z]*i/
applied to"titanic"
will produce the biggest match,"titani"
. By adding a question mark like so/t[a-z]*?i/
, the match behaves in a lazy manner and the smallest match is returned"ti"
.Create capture groups by using parenthesis
(...)
, which can be referenced subsequently inside the regular expression by number\1
,\2
, etc. They can also be referenced inreplace
like so$1
,$2
, etc.
Debugging
- Three types of bugs:
- syntax errors that prevent a program from running,
- runtime errors when code fails to execute or has unexpected behavior, and
- semantic (or logical) errors when code doesn't do what it's meant to.
Object Oriented Programming
An object is just a data structure that holds property/value pairs. The values can be of any arbitrary type: strings, numbers, objects... When a property has a value of type Function, we call it a method.
Constructors are functions that create new objects. They follow a few conventions:
They are defined with a capitalized name to distinguish them from other functions that are not constructors.
They use the keyword
this
to set properties of the object they will create. Inside the constructor,this
refers to the new object it will create.They define properties and behaviors instead of returning a value as other functions might.
You can use
obj instanceof Obj
to test if a specificobj
object is an instance of theObj
constructor.An object has two types of properties: own properties and prototype properties. Own properties are defined directly on the object instance itself. And prototype properties are defined on the prototype.
.hasOwnProperties(key)
returnsfalse
for prototype properties, but thein
operator works with both. But it's more complicated, so check Enumerability and ownership of propertiesEnumerable properties are those properties whose internal enumerable flag is set to true, which is the default for properties created via simple assignment or via a property initializer (properties defined via Object.defineProperty and such default enumerable to false). Enumerable properties show up in for...in loops unless the property's key is a Symbol. Ownership of properties is determined by whether the property belongs to the object directly and not to its prototype chain. Properties of an object can also be retrieved in total.
Manually setting the prototype of a new object will erase (overwrite, I guess) the constructor property. One solution is to include the constructor in the object literal we're using to overwrite
prototype
.javascriptfunction Dog(name) {this.name = name;}// Modify the code below this lineDog.prototype = {constructor: Dog,numLegs: 2,eat: function() {console.log('nom nom nom');},describe: function() {console.log('My name is ' + this.name);}};
Functional programming
Functional programming is about:
Isolated functions - there is no dependence on the state of the program, which includes global variables that are subject to change
Pure functions - the same input always gives the same output
Functions with limited side effects - any changes, or mutations, to the state of the program outside the function are carefully controlled
Functions passed as arguments are referred to as callbacks.
Functions that can be assigned to a variable, passed into another function, or returned from another function just like any other normal value, are called first class functions. All functions are first class in JavaScript.
Functions that take functions as arguments or return functions are called higher order functions. The functions that are passed as arguments or returned as results are called lambdas.
In functional programming, changing or altering things is called mutation, and the outcome is called a side effect. A function, ideally, should be a pure function, meaning that it does not cause any side effects.
Another principle of functional programming is to always declare your dependencies explicitly. This means if a function depends on a variable or object being present, then pass that variable or object directly into the function as an argument.
reduce
caveat: the first time the callback is called,accumulator
andcurrentValue
can be one of two values. IfinitialValue
is provided in the call toreduce()
, thenaccumulator
will be equal toinitialValue
, andcurrentValue
will be equal to the first value in the array. If noinitialValue
is provided, thenaccumulator
will be equal to the first value in the array, andcurrentValue
will be equal to the second.