Preamble
This is a self-study effort from January 2025. The scripts I wrote for the chapter exercises are at the bottom of this page's source code.
I've been eying this textbook for a few days now, but since I have this website, I figure this is a good place to host my notes in an environment where I can actually execute JavaScript. I didn't have a place to put it, though, so I added an extra index page to branch my site structure off into a self-development page, where I have the link to this page. It doesn't take long to actually make pages, but because they're my pages, I get to choose to give them novel creative designs, which adds artistic & troubleshooting processes on top of the coding.
All of this just to start studying, not that any of that was necessary. I enjoy the content of the work and the learning involved, if that's not made apparent by the existence of this page. What kind of fool works without being told? One who's curious or creative or otherwise self-driven... that kind of fool! And now, I'll fool around with the content of this book.
Chapter 0 - Introduction
"A sense of what a good program looks like is developed with practice, not learned from a list of rules."
This chapter discusses very basic concepts on the what & why of programming & JavaScript, so the part that shines out to me is the above quote. The author isn't teaching from a place of telling you what should be done, but rather from preparing you to tell yourself what should be done.
One who's not an artist doesn't know the rules. A good artist knows the rules well and follows them well. A great artist knows the rules well... and breaks them. Not by simply ignoring them, but by deconstructing the very reasons those rules exist.
The author and I share some values. That's what I've learned from this book's introduction.
Chapter 1 - Values, Types, and Operators
That's not a bug, it's a feature.
This chapter had lots of basic operations, plus the nullish operator ("??"), which browsers didn't even widely support until 2020. I'm not sure a great number of people formally educated until just recently would even know about it if they're not doing occasional reviews of the base technology like I'm doing here. Even then, lots of documentation was made before this was well-supported. It's a case where the latest textbook edition is necessary if it's to supply this knowledge. Sure enough, this feature isn't in the same textbook's previous edition.
These are some concepts from this chapter that I haven't been using in my JavaScript:
-
2.998e8
// yields 299800000 -
x = a && b;
// where a is not boolean; only gives b if a is truthy, and gives back the falsey a otherwise -
x = a || b;
// where a is not boolean; gives a if it's truthy, and gives the default value b otherwise -
x = a ?? b;
// where a is not boolean; gives a if it's not null or undefined (so can give falsey a values like 0 or ""), and gives the default value b otherwise -
NaN != NaN
Here are some concepts I know that supplement this chapter:
-
+'5' + 1 === 6 //
plus sign as a unary operator explicitly coerces a string to a number, though it's not as complete as parseInt('5'), as +'5px' would instead yield NaN -
!!'5' === true; !!{} === true; !!0 === false;
// double exclamation point as a unary operator explicitly coerces any value to a boolean -
!'5' === false; !{} === false; !0 === true;
// single exclamation point as a unary operator explicitly converts any value to its opposite boolean -
299_800_000
// yields 299800000; underscores can be added in any numeric literals to make them more readable
Between these two lists, some of them are maybe not intended by the language, but they're all consistent enough to be used as outright features.
Chapter 2 - Program Structure
The devil's in the details.
I already knew everything that was in this chapter, or at
least, I knew everything it intended for me to know. Of
the (offhand-mentioned) list of reserved keywords, I
haven't been using most of the object-oriented ones in my
JavaScript. The keywords async
and
await
are conspicuously missing from the
chapter's list of keywords, and I don't think I've ever
used the keywords with
or yield
.
None of this is in the intended scope of the chapter, but
if I'm brushing up on my JavaScript, I think it's good to
look out for places where I can be thorough.
The with
keyword is deprecated, but here's
my first script using yield
. The below
elements generate a number between the lower & upper
bounds, then stops generating after 10 yields, unless you
change the bounds:
[press the button to
yield
a value from a generator
function]
Chapter 2 Exercises
-
Exercise 2.1 - Looping a Triangle
-
Exercise 2.2 - FizzBuzz
-
Exercise 2.3 - Chessboard
Chapter 3 - Functions
Every instruction is made of smaller instructions, every little bit's got a million bits.
These chapters are getting longer now. There's a little quirk to be found in a chapter that instructs how to write sets of instructions, while part of that instruction is an example specifically about recursion.
The book doesn't specifically endorse one way or the
other when it comes to creating functions, but I'm bought
in on the arrow functions. I always thought that unless
two functions must reference one another, it's bad form to
use a function before it's defined in the code. So I
didn't use this quirk of function fun() {}
declaration notation and wound up forgetting about it.
Plus, this notation never lets you define fun
as a constant, and I always define functions as
const
whenever possible. const fun = ()
=> {}
is valid JavaScript, and const function
fun() {}
is not.
I should also note that I'd forgotten about default
function inputs that replace undefined ones, where a
function is defined (a, b = 'default input') =>
{}
so that if a function call is missing an
argument, it can fill b
in with the
assignment expression in the function arguments
definition.
Chapter 3 Exercises
-
Exercise 3.1 - Minimum
Their minimum: -
Exercise 3.2 - Recursion
Even or odd? -
Exercise 3.3 - Bean Counting
CountBs:
CountChar:
Chapter 4 - Data Structures: Objects and Arrays
This is the longest chapter in the book!
Sure enough, my ability with objects in JavaScript has
been pretty under-utilized. In fact, I probably learned
things in the wrong order the first time around, because I
never use the in
or delete
keywords, because I didn't understand them when I first
learned about them, because I wasn't using JavaScript
objects until later on! So here's another list of things I
haven't been using in my JavaScript:
-
for(const keyName in object) { ... }
// for-in loops iterate over the keys in an object -
const obj = {a, b}
// gives the keys "a" and "b" to an object and assigns them the corresponding values -
obj['2']; obj['two words']; {"two words": 2, "fun()": 'yay'}
// can assign object keys using otherwise invalid variable names, by using quotes -
delete obj.a
// removes a key from an object -
Object.assign(a, b, c, ...)
// merges objects, copying all properties from later objects into the first object -
arr[-2]; arr['three']
// arrays can have any key because they're just objects; I think it's bad form, but it's good to know -
arr.includes('somevalue', num)
// checks if an array has a given value at or above the index number num -
'somekey' in obj
// returns a boolean representing whether some keyname is in the object -
let array2 = array1.slice()
// slice an array without arguments to just return a new independent copy of the array -
str.padStart(8, "0")
// pads a string; if this string is not 8 characters long, leading 0s are added until it is -
arr.join(' - ')
// joins all elements of an array into a single string, with the argument being added between each entry; [1, 2, 3] -> 1 - 2 - 3 -
let array2 = ['a', ...array1, 'z']
// puts all elements from array1 into array2, between the 'a' and 'z' values -
([a, b, c, d]) => {...}
// assigns values from an input array to the values of the variables a, b, c, and d; more wieldy than just using the array -
JSON.stringify({}); JSON.parse(someJsonString);
// converts to and from JSON strings, largely for API calls -
arr?.[0]; obj?.fun?.()
// the winking elvis operator's notation for arrays & function calls -
n => ({prop: n})
// shorthand for an arrow function that returns an object; parentheses keep object from being interpreted as a function body
In spite of the increasing verbosity of the chapters, I
know some things would remain a complete mystery for an
actual beginner reading this book. In the "Destructuring"
section, it says you can use square brackets to "look
inside" of an array value to bind its contents, but it
doesn't give an example, making this a nearly
indecipherable remark if you don't see an example
(let [a, b, c, d] = someArrayWith4Elements
).
The chapter had a bit of math, too, which is cool. It sometimes takes lots of math & working out general formulas to make my scripts act the way I want them to, so seeing someone else using math as part of their process is refreshing. That's surprisingly uncommon for what programming fundamentally is.
Chapter 4 Exercises
-
Exercise 4.1 - The Sum of a Range
Range values:
Sum of the range: -
Exercise 4.2 - Reversing an Array
Reversed array:
Array before in-place reversal:
Array after in-place reversal: -
Exercise 4.3 - A List
List constructed from array:
Array reconstructed from list:
Nth element from the list: -
Exercise 4.4 - Deep Comparison
Are they deeply equal?
Chapter 5 - Higher-order Functions
Yo, dawg, I heard you like functions.
Well, I looked ahead and saw that chaper 4 was the longest chapter in the entire book. This chapter was significantly shorter, though it also covers inbuilt language specifics that are wheels I've tended to reinvent rather than using their implementations that are available by default. Hopefully by having run by these here, I'll have better recall when it comes time to use them:
-
filteredArray = array.filter(item => { return boolean; })
// array function to filter out items that return falsey when passed to the given function -
mappedArray = array.map(item => { return doStuff(item); })
// array function to process each item into a value derived from that item, then return those derived values in an array -
value = array.reduce((item1, item2) => { return combinedItem; }, startItem?)
// array function that combines the first value with each subsequent value, using the combining function, iteratively until they're all combined, returning the combination -
array.some(arg => { return boolean; })
// array function returning true if ANY of its values return truthy when passed into the given function -
array.find( item => { return boolean; } )
// array function finding the first element that returns true when it's passed to the given function -
(a, {b}) => { ... }
// asserts that b is a property of an object and uses that property by its value when it's in the function
Chapter 5 Exercises
-
Exercise 5.1 - Flattening
Flattened array: -
Exercise 5.2 - Your Own Loop
This exercise is disabled on the live page. Below is my solution; it can be pasted in the code area in the "Your Own Loop" section here on the textbook site.
const loop = (value, test, update, body) => { let i = value; while(test(i)) { body(i); i = update(i); console.log(i); console.log(output1.innerText); } return i; }; loop(3, n => n > 0, n => n - 1, console.log); // → 3 // → 2 // → 1
-
Exercise 5.3 - Everything
Any exercise whose input would require arbitrary function definitions won't be allowed to run off of UI elements on the live site. My solution below can be checked by pasting it into the code section under the "Everything" header here on the textbook site.
const every = (arr, test) => { for(const item of arr) { if(!test(item)) { return false; } } return true; } console.log(every([1, 3, 5], n => n < 10)); // → true console.log(every([2, 4, 16], n => n < 10)); // → false console.log(every([], n => n < 10)); // → true
-
Exercise 5.4 - Dominant Writing Direction
This exercise has in-page dependencies on the Eloquent JavaScript site. My solution is below and can be pasted & run on the code section near the bottom of this page.
const dominantDirection = (text) => countBy(text, n => characterScript(n.codePointAt(0))) .filter(n => n.name != null) .reduce((a, b) => a.count > b.count ? a : b) .name .direction ; console.log(dominantDirection("Hello!")); // → ltr console.log(dominantDirection("Hey, مساء الخير")); // → rtl
Chapter 6 - The Secret Life of Objects
It's short for "classification."
There's something so arcane about the Symbol type. When a Symbol is instantiated, I imagine a unique glyph appearing and being used as the label for whatever property it corresponds to.
This chapter had more tinkering with objects, so here are some more concepts I haven't been using in my code:
-
const fun = () => { console.log(this) }; const a = {fun}, b = {fun}; a.fun(); b.fun();
// the "this" keyword in functions binds dynamically to any object that uses the function as a method -
const fun = (property) => { console.log(this[property]) }; fun.call(obj, fun);
// "this" can also be dynamically bound by using an object in the function's "call" method -
const obj = { fun(arg) { return () => { return this[arg] } } };
// shorthand java-like object method assignment, and "this" is usable in ARROW functions defined in the method (not "function fun()"" declarations) -
Object.getPrototypeOf(obj)
// returns the prototype of an object, which is like a parent object it's extending; obj always has access to all properties of its prototype, even if obj itself is empty -
let obj2 = Object.create(obj1);
// creates an empty obj2 that has access to all the properties of obj1; Object.getPrototypeOf(obj2) will return obj1 -
"function constructObj(arg) {const obj2 = Object.create(obj); obj2.instanceProperty = arg; return obj2;}" ~= "class Obj {constructor(arg) {this.instanceProperty = arg} classProperty: }"
// class instead of prototype as an object's template; its prototype only any methods defined in the class - // a class is fundamentally just a function with a .prototype property where it references methods added to the class, with the new keyword doing the work to make objects invoked with the constructor contain the methods in .prototype; was confusing me until I read this rundown
- // only non-arrow functions have the .prototype property, which is why only arrow functions work well with "this" bindings when they're defined within a class method's body
-
const SomeClass = class { ... }
// constant class name binding declaration -
let obj = new class { log() { console.log(this) } }; obj.log();
// object declaration as an instance of an anonymous class -
class { #secretField = 3; #secretMethod() { console.log('this can only be called from inside the class') } publicMethod() { this.#secretMethod(); } }
// a class can have private properties by starting their names with # - // private properties MUST be declared within the class; only public properties can be assigned to the class or object instance after the class is defined
-
SomeClass.prototype.property2 = 'new property';
// property2 becomes visible in all objects that are instances of SomeClass -
SomeClass.prototype.method2 = function() { console.log(this); };
// for adding new methods to the prototype, it's best to use the function keyword instead of an arrow function, so that any "this" instances don't bind to the global scope -
const pureObject = Object.create(null);
// creates an object with no prototype; only has what you define without inheriting any properties from Object.prototype -
Object.keys(obj);
// note that it does not return its prototype's values, only the object's own values -
let a = Symbol(2); let obj = { a: 2, [a]: 'symbol property', b: 4}; obj.a === 2; obj[a] === 'symbol property';
// can define a symbol as an object property name by giving it square brackets in the object definition declaration -
class { static fun() { new this() } }
// classes can have static methods that are class members instead of instance members, and new this() calls the constructor of the class where it's contained -
class IterableThing{ constructor(){} [Symbol.iterator]() { return new class ThingIterator{ constructor(){} next() { return {value, done} } } } }
// iterator interface; makes the class objects usable for a for-of loop and for the destructuring operator ("...thing") -
static staticProperty = 'some value'; static staticMethod() { return this.staticProperty }
// static methods can access static properties with the this keyword, as the object instance is the class constructor in this context
I already knew about maps, the "extends" & "static" & "super" keywords work like in Java. The syntax is similar, but you can tell that all things about JavaScript classes are syntactic construct made by composing objects & functions such that they can look & act like Java classes, with the syntax hiding all of the complexity required for that underneath. It's not a fundamental of the language like it is in Java; it's a bunch of other concepts all coming together to make this, which makes it harder to wrap your head around, despite the code itself being mostly familiar.
Chapter 6 Exercises
-
Exercise 6.1 - A Vector Type
Vector 1:
Vector 2:
Vector 1 + Vector 2:
Vector 1 - Vector 2:
Vector 1 length:
Vector 2 length: -
Exercise 6.2 - Groups
Add this value to the group:
Delete this value from the group:
Check if the group has this value:
Does the group have the above value?Yes
-
Exercise 6.3 - Iterable Groups
Add this value to the group:
Delete this value from the group:
Check if the group has this value:
Does the group have the above value?Yes
Iterative printout of values in this Group:
Chapter 7 - Project: A Robot
Go, RoboJackets!
--
Chapter 7 Exercises
Chapter 8 - Bugs and Errors
--
Chapter 8 Exercises
Chapter 9 - Regular Expressions
--
Chapter 9 Exercises
Chapter 10 - Modules
--
Chapter 10 Exercises
Chapter 11 - Asynchronous Programming
--
Chapter 11 Exercises
Chapter 12 - Project: A Programming Language
--
Chapter 12 Exercises
Chapter 13 - JavaScript and the Browser
--
Chapter 13 Exercises
Chapter 14 - The Document Object Model
--
Chapter 14 Exercises
Chapter 15 - Handling Events
--
Chapter 15 Exercises
Chapter 16 - Project: A Platform Game
--
Chapter 16 Exercises
Chapter 17 - Drawing on Canvas
--
Chapter 17 Exercises
Chapter 18 - HTTP and Forms
--
Chapter 18 Exercises
Chapter 19 - Project: A Pixel Art Editor
--
Chapter 19 Exercises
Chapter 20 - Node.js
--
Chapter 20 Exercises
Chapter 21 - Project: Skill-Sharing Website
--
Chapter 21 Exercises
Reflection
--