Effective JavaScript Reading Notes

· 2 min read

I finally finished reading this book intermittently

This book explains JavaScript key concepts in a recipe-like format. I learned a lot from it, so I’m making notes here

Versions

  1. ES is the standard, JS is the implementation. Since JS in web pages executes on the client side, different clients (browsers) have different support for JS, HTML, and CSS. This is why we have compatibility issues - the same JS code may produce different results in different browsers.
  2. With TypeScript and Babel available now, we can actually write newer ES versions like ES6, 7, 8 in development, then use TSC and Babel to compile to target JS versions, while adding polyfills for unsupported syntax.

Numeric Computation

  1. Unlike other languages such as Java and Python, JavaScript has only one numeric type for all numbers including integers and decimals — Number. It follows the IEEE 754 standard, using 64-bit fixed length (8 bytes) representation, which is the standard double-precision floating-point number (compared to float 32-bit single precision)
  2. Theoretically, it’s impossible to guarantee precision when storing infinite decimals in finite space. So precision issues are inevitable, like with our 1/3.
  3. Due to limited space, there’s also the big number crisis. Since 64 bits are finite, the maximum value is fixed at 9007199254740991. What happens when we exceed it? The crisis is inevitable, but fortunately there’s a new built-in type BigInt
  4. BigInt serves exactly what its name implies => for larger integer values, though it’s still 8 bytes

Note: This issue doesn’t only occur in JavaScript. Almost all programming languages use IEEE-754 floating-point representation, and any programming language using binary floating-point numbers will have this problem. But languages like Java have BigDecimal class for direct use, so the problem is less prominent.

Floating-Point Precision Issues

Use existing libraries, recommend big.js & mathjs. The principle is to convert floating-point numbers to strings and simulate actual arithmetic processes

Prefer Primitive Types Over Wrapper Objects

  • For example, when declaring strings, we can use new String('hello'), String('hello'), 'hello', but note that new String is actually a String object, not a primitive data type.
  • For primitive types, generally don’t use new object wrappers for declaration.

Limitations of Semicolon Insertion

In the following code, sample1 runs OK, but sample2 doesn’t return the expected result. Why? Because of automatic semicolon insertion (ASI), which takes effect during JS syntax parsing

var name = "ESLint"
var website = "eslint.org";

console.log(name);
console.log(website);
function sayName(){
return
{
    name: "ESLint"
};
}

console.log(sayName()); // undefined

Notes

  • ASI is a fallback (second choice). When encountering line terminators, the compiler always first tries to parse the symbol stream separated by line terminators as a single statement (with a few exceptions: return, throw, break, continue, yield, ++, –). Only when it doesn’t conform to correct syntax does it fall back to enabling the ASI mechanism, treating the line terminator-separated symbol stream as two statements (commonly called “inserting semicolons”).
  • The aforementioned exceptions don’t allow line terminators to exist. If there’s a line terminator in a statement, the parser will prioritize considering the line terminator as the end of the statement, which is called restricted production in the ECMAScript standard.

Variable Scope

Higher-Order Functions

The characteristic of higher-order functions is taking functions as parameters or returning functions as results. Methods like Array.map and sort all accept a function. Higher-order functions are a way to abstract code and improve reusability. So, worth practicing.

Arrays and Dictionaries

Compared to dictionaries, arrays have order, while dictionaries don’t. When using for…in on dictionary data, the order might not be what we expect, as shown in the example below. This is because during traversal, keys are parseFloat’d, values are obtained and then sorted.

const userMap = {
  hello: "alan",
  '1': "helen",
};

for (const key in userMap) {
  console.log(key);
}

// 1
// hello

Notes

  • Object keys are always strings, even when traversing an array

undefined Values

Like Java, C and other languages that represent “null” values, JavaScript is special in having both null and undefined.

Similarities

Equality testing between null and undefined results in true, console.log(null==undefined); \\ true, undefined value is derived from null value.

Concurrency

  • JavaScript implements single-threaded execution to avoid complexity
  • Browsers are multi-process, that’s why Chrome consumes so many resources
  • Whether it’s multithreading, multiprocessing, or coroutines, they’re all for better utilization of computer resources

Processes

A process is an execution instance of an application. Each process consists of private virtual address space, code, data, and other system resources. Processes can request, create, and use system resources (such as independent memory areas) during execution, and these resources are destroyed when the process terminates. Threads are independent execution units within a process. Different threads can share process resources, so in multithreaded situations, special attention must be paid to access control of critical resources.

As shown below in system process management, we can see Chrome has more than one process.

JS’s Single-Threaded Nature Doesn’t Contradict Promise.all Parallel Loading

  • Promise is a pattern, a way to organize asynchronous code. It solves callback hell but is still asynchronous.
  • Promise.all executes a bunch of asynchronous operations, then retrieves them all at once. The N asynchronous operations started by Promise.all don’t affect each other

Final Thoughts

  1. One mark of an excellent developer is that they can always explain why something is designed or done a certain way, while non-excellent developers often can’t articulate the reasoning.
  2. After finishing this book, I feel JavaScript isn’t that difficult, or rather, high-level languages aren’t that difficult. Understanding their design purposes and patterns should make them much easier to work with.

References