Statistics
3
Views
0
Downloads
0
Donations
Support
Share
Uploader

高宏飞

Shared on 2026-03-03

AuthorSimon Høiberg

In this book you will learn how professionals write JavaScript - in the industry. You know, out there in the real world.

Tags
No tags
Publisher: simonhoiberg.com
Publish Year: 2021
Language: 英文
Pages: 71
File Format: PDF
File Size: 3.1 MB
Support Statistics
¥.00 · 0times
Text Preview (First 20 pages)
Registered users can read the full content for free

Register as a Gaohf Library member to read the complete e-book online for free and enjoy a better reading experience.

1
Introduction 4 Functional style 5 Imperative vs. declarative 5 Working with arrays 10 Avoid using classes 18 Working with instances when you really don’t have to 19 Classes vs Hooks in React 23 Create your own abstractions 25 Control flows 28 Guard clauses 28 Skip the ‘else’ part 31 Using a switch-statement 35 Using functions and partial applications 36 Code hygiene & good practices 42 Pass arguments as an object 42 Return associated data as tuples 46 Do not extend builtins 47 Avoid default exports 48 Poor Discoverability 49 Annoying when using CommonJS 49 Annoying when using Dynamic Imports 49 Name Protection 49 Re-exporting 49 Drop the single-letter variable names 50 Arrow function vs. function declaration 51 2
TypeScript 52 Don’t overdo it 52 Let TypeScript infer the type 54 Avoid using any 56 React 57 Use React hooks 57 Don’t worry about arrow functions in JSX 57 Don’t return JSX from inner functions 59 Ternary inside the JSX 60 Split into a separate component 60 Don’t wrap useEffect in an async IIFE 61 Don’t overuse the inbuilt hooks 62 Stop overusing useMemo 62 Stop overusing useCallback 64 NodeJS & AWS Lambda 65 Use promises instead of callbacks 65 Using promisify 66 Using module/promises 67 Async handlers in AWS Lambda 67 Final words 69 Which conventions should I use? 69 Additional resources 70 3
Introduction I have had a front-row seat while JavaScript has taken over the industry. In the past ten years of working as a freelance consultant, I’ve had the joy of working with many different teams. I’ve participated in countless PR code reviews and many heated discussions about JavaScript, best practices, clean code, patterns, and coding styles. I have taught JavaScript, React, and NodeJS on various talks and workshops, and furthermore, I’ve spent the last year notoriously presenting my Twitter audience with small bits of code, asking them what they preferred and if they would have approved it in a PR. Here are my findings, impressions, and personal experience. All put together in an easy-to-digest e-book including examples and explanations. This book is opinionated. For each and every example in this book, you will find developers in the industry who disagree. This book teaches industry preferences and standards. But it is, by definition, opinionated. This is not a JavaScript fundamentals book. Do note, that this book assumes fundamental understanding of the JavaScript language. 4
Functional style JavaScript is a multi-paradigm programming language. This means that the language is open for programming in different styles, including object-oriented, procedural, prototypal, and functional. By far, the most common styles you see are object-oriented and functional. Even though object-oriented languages such as Java and C# have had an enormous impact on the industry, the functional style JavaScript is the most popular and accepted in 2021. This is where you should be heading. Imperative vs. declarative Object-oriented programming follows an imperative paradigm. Functional programming follows a declarative paradigm. Let’s look at the difference. Imperative programming focuses on how you want something done. You alter the state of your program step by step. Declarative programming focuses on what the end result will be. How to obtain that result is less interesting, as long as the process of obtaining it does not alter the state of your program. 5
When a function carries out a task in a deterministic way without changing its environment (changing state in its surroundings), we call it pure. Let’s say we want to iterate through a list of numbers and multiply them all by 2. An imperative style would look something like this. Simple and straightforward. But there are two key observations we need to make here: 1. The function multiplyAll does not have a return value. Since it’s not returning anything, we cannot determine the result based on the input. Hence, it’s not pure. 2. The original listOfNumbers array gets mutated. The function alters (changes the state) of the input given as an argument. Hence, it’s not immutable. 6
These two simple behaviors are likely to result in bugs, code that is hard to debug, hard to test, and is likely to break your application at scale! On a lot of professional teams, this code would be immediately rejected in a Pull Request. Let’s rewrite it to follow a declarative style instead. Well, isn’t this our lucky day? JavaScript has a method on the Array prototype built in that does exactly what we need. It’s called map. Let’s do a few observations again: 1. The function map has a return value. It’s a list with each element altered as specified in the callback function we provide. Map doesn’t change its surroundings and will return the same result every time, given the same callback and input. Hence, map is pure. 2. The original listOfNumbers stays untouched. Map will create a new copy of the array for us, and alter that one instead. Hence, map is immutable. 7
As it turns out, all the Array-methods (forEach, Map, Reduce, Filter, …) are following a declarative programming style. The code becomes way cleaner, easier to test, less prone to introduce bugs, and much more likely to be approved in a Pull Request on most professional teams today. Be careful about the pitfalls, though. The Array-methods are only pure and immutable to the extent that you use them as intended. This is an example I’ve seen very often. The people object is still mutated on, and the surroundings are still changed. Doing it as part of reduce isn't changing this. 8
Or how about this? It’s as imperative and mutable as it can possibly be! Why not just use a regular for-loop then? It has better performance. Similarly, utility libraries like lodash and date-fns, and UI libraries like React - that are all built with a functional and declarative style in mind - are only going to offer all its benefits if it’s used the way it was intended. I’m my career as a consultant, I’ve often witnessed chaotic, careless - and sometimes tragically funny - mixes of styles piled on top of each other, which totally defeats the purpose of keeping consistent with conventions and coding styles throughout the application. Of course, software development often goes fast, and there are many deadlines, demands from product owners, bugs to fix fast, and so on. So the key is to get a good habit of writing clean and declarative code under your skin and understand when to be stubborn about it and when to simply let go. In the rest of this chapter, I will provide some of the most common examples of imperative code that could (and should) be refactored into declarative code and how to do it. 9
Working with arrays In JavaScript (and in programming, generally), you’ll find yourself working with arrays a lot. This is why the famous array methods introduced in ES6 became so popular. They really make our lives easier. And recall: They are following a declarative programming style. In this example, we want to filter a list of candidates to only include candidates who are also active members (exists in the activeMembers array). Below is an example of doing this imperatively. 10
There are two red flags that should pop up in your mind here. 1. You are declaring an array outside the body of the loop. 2. You are using the push method to populate an array. As a rule of thumb: Whenever you’re about to call the push method, ask yourself if this can be expressed in a declarative way instead. The push method is mutating on the array. Let’s refactor it. Ahh, much better! No surrounding states are changed. Nothing is mutated on. The activeCandidates is declared and directly assigned the result of filter, which takes care of the job for us. 11
Let’s take another example. Here, we want to iterate through a list of numbers and find the sum. Below is an example of doing this imperatively. There are two red flags that should pop up in your mind here. 1. You are declaring a variable outside the body of the loop. 2. You are using the let keyword to initiate the variable. As a rule of thumb: Whenever you find yourself using the let keyword, ask yourself if you can achieve the desired result without reassigning the variable. In most cases, you don’t want to use let. You want to initiate and assign variables immediately using const. 12
Let’s refactor it. Perfect! One line of code. No surrounding states are changed. No variables are being reassigned. I sometimes hear people propose this argument: “Reduce is difficult to understand. If you have juniors on your team, you may want to go with the imperative approach”. I personally couldn’t disagree more. It all depends on its use - but when reduce is kept simple, as in the example above, it is perfectly within most junior developers' capability to comprehend. This is often a bad excuse from mid-levels and seniors who still haven’t adapted to this way of writing code but lack clear arguments for why they would stick in their old imperative ways. Let’s take another example. Sorting! 13
This one gets a bit messier. Take a look at the code below. At first glance, this looks good. We’re not using let, and we’re not mutating on the original array using something like push. We use an Array-method that declaratively returns the desired result. But take a look at the console.log statement. Yes. JavaScript can be awful like this. It turns out that the sort method is really old, and does not create a copy of the original array. Instead, it both mutates on the original array and returns its own array from the method call. Weird? Yes. But there are a handful of old Array-methods that do this. Be careful with push, shift, unshift, pop, reverse, splice, sort, and fill. Fortunately, as we saw in the example from before, most often we can simply avoid calling these methods at all, to stay out of trouble. 14
However, there are cases, like using sort, where we have to use a method that mutates the original array, in lack of better options. Array destructuring to the rescue! Whenever these occasions arise, make sure to manually copy the array first, before performing an operation on it. It’s as simple as this. That [...grades] makes the entire difference. Get this habit into your fingers. 15
Let’s look at an example using asynchronous operations. Iterative operations including asynchronous behavior can be a little more tricky to do using a declarative style. Let’s say we have a list of names. For each name, we want to make an API call and get some information, and then keep a new list with this collection of information. A typical imperative approach may look like this. Using an imperative approach makes a bit more sense in this case. Refactoring to using map or forEach is not that straightforward here. 16
The callbacks provided to map or forEach (or any of the array-methods) are not awaited, so we have no way of knowing when the full collection of information is done and ready to use. However, there is still a way we can write this in a nice, declarative way - and it even includes a bonus takeaway! Using the Promise.all method. Awesome! Now, map returns a list of promises, and the Promise.all method takes a list of promises and resolves them in parallel. Not only did the code become much more nice and clean - but we also benefit from the fact that the promises are not resolved sequentially, which speeds up the process and increases performance. 17
Avoid using classes Ahh, classes. At the very root of object-oriented programming lies the concept of classes. Classes are blueprints for creating objects. They encapsulate data along with code to mutate on that data. In JavaScript, classes are built on prototypes and are used as a template for creating objects. They are - as in any other programming language - inherently imperative in their nature. The use of classes has its place. It does make sense on some occasions. But most often, you can avoid using them - and if you can, you should. So generally, whenever you are about to use a class declaration, ask yourself if it’s really necessary. Can you express the logic you need in a declarative way instead, using only functions? In 9/10 cases, I bet you can! Let’s take a look at some of the most common uses of classes, which can easily be refactored into using a declarative programming style instead. 18
Working with instances when you really don’t have to Let’s look at this class which will format a name and creates a greeting. 19
The idea here is to create a class that encapsulates the logic of building our name, so the consumer doesn’t have to worry about implementation details and each step in the process. And that’s great! But the thing is - there is no need to work with instances in this case. Having to use the new keyword to create a new NameBuilder instance doesn’t serve any kind of purpose here. Yet, this is the most common use of classes I’ve seen in the industry. The intention is good - but the implementation is pointless. 20