Skip to content

Instantly share code, notes, and snippets.

@MarioAndWario
Last active August 25, 2023 00:49
Show Gist options
  • Save MarioAndWario/ecb8afc3b2cf015e12f05a04ed51c5c7 to your computer and use it in GitHub Desktop.
Save MarioAndWario/ecb8afc3b2cf015e12f05a04ed51c5c7 to your computer and use it in GitHub Desktop.
Study notes of "Eloquent JavaScript"

Variable

Bindings declared with let and const are local to the block that they are declared in, so if you create one of those inside of a loop, the code before and after the loop cannot “see” it. In pre-2015 JavaScript, only functions created new scopes, so old-style bindings, created with the var keyword, are visible throughout the whole function that they appear in—or throughout the global scope, if they are not in a function.

let x = 10;
if (true) {
  let y = 20;
  var z = 30;
  console.log(x + y + z);
  // → 60
}
// y is not visible here
console.log(x + z);
// → 40

Function

Basics

const foo = () => {
    console.log("Hello World");
}

const bar = function(){
    return 1;
}

function foobar(){
    return "Hello World";
}

let h = a => a % 3;

JavaScript is extremely broad-minded about the number of arguments you pass to a function. If you pass too many, the extra ones are ignored. If you pass too few, the missing parameters get assigned the value undefined.

Closure

function wrapValue(n) {
  let local = n;
  return () => local;
}

let wrap1 = wrapValue(1);
let wrap2 = wrapValue(2);
console.log(wrap1());
// → 1
console.log(wrap2());
// → 2

This feature—being able to reference a specific instance of a local binding in an enclosing scope—is called closure. A function that references bindings from local scopes around it is called a closure.

A good mental model is to think of function values as containing both the code in their body and the environment in which they are created. When called, the function body sees the environment in which it was created, not the environment in which it is called.

Properties

The two main ways to access properties in JavaScript are with a dot and with square brackets. Both value.x and value[x] access a property on value—but not necessarily the same property. The difference is in how x is interpreted. When using a dot, the word after the dot is the literal name of the property. When using square brackets, the expression between the brackets is evaluated to get the property name. Whereas value.x fetches the property of value named “x”, value[x] tries to evaluate the expression x and uses the result, converted to a string, as the property name.

Property names are strings. They can be any string, but the dot notation works only with names that look like valid binding names. So if you want to access a property named 2 or John Doe, you must use square brackets: value[2] or value["John Doe"].

The elements in an array are stored as the array’s properties, using numbers as property names. Because you can’t use the dot notation with numbers and usually want to use a binding that holds the index anyway, you have to use the bracket notation to get at them.

Objects

Braces have two meanings in JavaScript. At the start of a statement, they start a block of statements. In any other position, they describe an object. Reading a property that doesn’t exist will give you the value undefined.

let day1 = {
  squirrel: false,
  events: ["work", "touched tree", "pizza", "running"]
};
console.log(day1.squirrel);
// → false
console.log(day1.wolf);
// → undefined

It is possible to assign a value to a property expression with the = operator. This will replace the property’s value if it already existed or create a new property on the object if it didn’t.

When you compare objects with JavaScript’s == operator, it compares by identity: it will produce true only if both objects are precisely the same value. Comparing different objects will return false, even if they have identical properties. There is no “deep” comparison operation built into JavaScript.

const score = {visitors: 0, home: 0};
// This is okay
score.visitors = 1;
// This isn't allowed
score = {visitors: 1, home: 1};

Containers

Array

Map

Prototype

In addition to their set of properties, most objects also have a prototype. A prototype is another object that is used as a fallback source of properties. When an object gets a request for a property that it does not have, its prototype will be searched for the property, then the prototype’s prototype, and so on.

The prototype relations of JavaScript objects form a tree-shaped structure, and at the root of this structure sits Object.prototype.

console.log(Object.getPrototypeOf({}) ==
            Object.prototype);
// → true

Many objects don’t directly have Object.prototype as their prototype but instead have another object that provides a different set of default properties. Functions derive from Function.prototype, and arrays derive from Array.prototype.

Class

Control flows

For loop

for (let entry of JOURNAL) {
  console.log(`${entry.events.length} events.`);
}

When a for loop looks like this, with the word of after a variable definition, it will loop over the elements of the value given after of. This works not only for arrays but also for strings and some other data structures.

Rest parameters

Receive rest parameter that is bound to an array.

function max(...numbers) {
  let result = -Infinity;
  for (let number of numbers) {
    if (number > result) result = number;
  }
  return result;
}
console.log(max(4, 1, 9, -2));
// → 9

Unpack an array

let numbers = [5, 1, 7];
console.log(max(...numbers));
// → 7

let words = ["never", "fully"];
console.log(["will", ...words, "understand"]);
// → ["will", "never", "fully", "understand"]

Destructuring

function phi([n00, n01, n10, n11]) {
  return (n11 * n00 - n10 * n01) /
    Math.sqrt((n10 + n11) * (n00 + n01) *
              (n01 + n11) * (n00 + n10));
}

If you know the value you are binding is an array, you can use square brackets to “look inside” of the value, binding its contents.

let {name} = {name: "Faraji", age: 23};
console.log(name);
// → Faraji

A similar trick works for objects, using braces instead of square brackets.

Functional programming

High-order functions

Functions that operate on other functions, either by taking them as arguments or by returning them, are called higher-order functions.

Higher-order functions allow us to abstract over actions, not just values. They come in several forms.

forEach

forEach provides something like a for/of loop as a higher-order function.

["A", "B"].forEach(l => console.log(l));

filter

The filter function, rather than deleting elements from the existing array, builds up a new array with only the elements that pass the test. This function is pure. It does not modify the array it is given.

console.log(SCRIPTS.filter(s => s.direction == "ttb"));

map

The map method transforms an array by applying a function to all of its elements and building a new array from the returned values. The new array will have the same length as the input array, but its content will have been mapped to a new form by the function.

let rtlScripts = SCRIPTS.filter(s => s.direction == "rtl");

reduce

The parameters to reduce are, apart from the array, a combining function and a start value. It builds a value by repeatedly taking a single element from the array and combining it with the current value.

let a = script.ranges.reduce((count, [from, to]) => {
    return count + (to - from);
  }, 0);

some

some takes a test function and tells you whether that function returns true for any of the elements in the array.

script.ranges.some(([from, to]) => {return code >= from && code < to;})

JSON

JavaScript gives us the functions JSON.stringify and JSON.parse to convert data to and from this format. The first takes a JavaScript value and returns a JSON-encoded string. The second takes such a string and converts it to the value it encodes.

Network protocol

A network protocol describes a style of communication over a network. There are protocols for sending email, for fetching email, for sharing files, and even for controlling computers that happen to be infected by malicious software.

HTTP

The Hypertext Transfer Protocol (HTTP) is a protocol for retrieving named resources (chunks of information, such as web pages or pictures). It specifies that the side making the request should start with a line like this, naming the resource and the version of the protocol that it is trying to use:

GET /index.html HTTP/1.1

TCP

The Transmission Control Protocol (TCP) is a protocol that ensure packages of bits arrive at the correct destination in the correct order.

A TCP connection works as follows: one computer must be waiting, or listening, for other computers to start talking to it. To be able to listen for different kinds of communication at the same time on a single machine, each listener has a number (called a port) associated with it. Most protocols specify which port should be used by default. For example, when we want to send an email using the SMTP protocol, the machine through which we send it is expected to be listening on port 25.

Another computer can then establish a connection by connecting to the target machine using the correct port number. If the target machine can be reached and is listening on that port, the connection is successfully created. The listening computer is called the server, and the connecting computer is called the client.

Such a connection acts as a two-way pipe through which bits can flow—the machines on both ends can put data into it.

World Wide Web

To become part of the Web, all you need to do is connect a machine to the Internet and have it listen on port 80 with the HTTP protocol so that other computers can ask it for documents.

Each document on the Web is named by a Uniform Resource Locator (URL), such as

http://eloquentjavascript.net/13_browser.html

Machines connected to the Internet get an IP address, which is a number that can be used to send messages to that machine, such as 128.108.0.0. Lists of more or less random numbers are hard to remember and awkward to type, so you can instead register a domain name for a specific address or set of addresses.

If you type this URL into your browser’s address bar, the browser will try to retrieve and display the document at that URL. First, your browser has to find out what address eloquentjavascript.net refers to. Then, using the HTTP protocol, it will make a connection to the server at that address and ask for the resource /13_browser.html. If all goes well, the server sends back a document, which your browser then displays on your screen.

HTML

HTML (Hypertext Markup Language) is the document format used for web pages. An HTML document contains text, as well as tags that give structure to the text, describing things such as links, paragraphs, and headings.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>My home page</title>
  </head>
  <body>
    <h1>My home page</h1>
    <p>Hello, I am Marijn and this is my home page.</p>
    <p>
      I also wrote a book! Read it
      <a href="http://eloquentjavascript.net">here</a>.
    </p>
  </body>
</html>

Some kinds of tags do not enclose anything and thus do not need to be closed. The metadata tag <meta charset="utf-8"> is an example of this.

In HTML, an ampersand (&) character followed by a name or character code and a semicolon (;) is called an entity and will be replaced by the character it encodes:

  • < <-- &lt;
  • > <-- &gt;
  • & <-- &amp;
  • " <-- &quot;

HTML and JavaScript

We can include a piece of JavaScript in a document:

<script>
  alert("hello!");
</script>

The <script> tag can be given an src attribute to fetch a script file (a text file containing a JavaScript program) from a URL.

<script src="code/hello.js"></script>

Some attributes can also contain a JavaScript program. The <button> tag shown next (which shows up as a button) has an onclick attribute. The attribute’s value will be run whenever the button is clicked.

<button onclick="alert('Boom!');">DO NOT PRESS</button>

JavaScript programs may inspect and interfere with the document that the browser is displaying through a data structure called the DOM (Document Object Model). This data structure represents the browser’s model of the document, and a JavaScript program can modify it to change the visible document.

The DOM is organized like a tree, in which elements are arranged hierarchically according to the structure of the document. The objects representing elements have properties such as parentNode and childNodes, which can be used to navigate through this tree.

The way a document is displayed can be influenced by styling, both by attaching styles to nodes directly and by defining rules that match certain nodes. There are many different style properties, such as color or display. JavaScript code can manipulate an element’s style directly through its style property.

Modules

Modules

A module is a piece of program that specifies which other pieces it relies on and which functionality it provides for other modules to use (its interface).

Packages

A package is a chunk of code that can be distributed (copied and installed). It may contain one or more modules and has information about which other packages it depends on. A package also usually comes with documentation explaining what it does so that people who didn’t write it might still be able to use it.

One package management service of JavaScript is NPM: an online service where one can download (and upload) packages and a program (bundled with Node.js) that helps you install and manage them.

CommonJS and require

const ordinal = require("ordinal");

Calling require to read the module's code, wrapping it in a function, and calling it.

ECMAScript modules and import

import ordinal from "ordinal";
import {days, months} from "date-names";

export function formatDate(date, format) { /* ... */ }

ES module imports happen before a module’s script starts running. That means import declarations may not appear inside functions or blocks, and the names of dependencies must be quoted strings, not arbitrary expressions.

Compilation

Some packages are originally written in modern JavaScript or its dialects (e.g., TypeScript), and they are compiled before publication. That is, they are translated to plain old JavaScript and minified (i.e., removing comments and white spaces).

Bundler

Because fetching a single big file tends to be faster than fetching a lot of tiny ones, web programmers use tools that roll their programs back into a single big file before publication to the web. Such tools are called bundlers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment