Code review in JavaScript: what to check so the code doesn't fall apart
\n\nHave you ever opened someone else's pull request and felt your stomach drop? Like looking at a tangled mess of wires where every knot is a potential bug. Code review in JavaScript is not just a checkbox in a task tracker. It's your last line of defense against chaos. Especially in the dynamic world of JS, where typing is an illusion and "magical" behavior is the norm.
\n\nIn this article, I'll tell you what to really pay attention to when reviewing JavaScript code. Forget pointless arguments about tabs vs spaces. We'll talk about things that directly affect stability, readability, and performance. This is the code review checklist that I use myself.
\n\n1. Function purity and absence of side effects
\n\nThe first and most important point. A function should do exactly one thing and do it well. If you see a function that simultaneously validates data, sends a request to the server, and updates global state — that's a red flag.
\n\nWhat to check:
\n- \n
- Number of arguments: Ideally 0, maximum 3. If more, put them in a config object. \n
- Mutation of input data: The function should not modify the passed array or object. This is a hard-to-catch bug. \n
- Side effects: Any change to the outside world (console.log, writing to a file, modifying the DOM) should be explicit and justified. \n
Bad example:
\nlet totalUsers = 0;\n\nfunction processUsers(users) {\n for (let i = 0; i < users.length; i++) {\n users[i].active = true; // Mutation of input data!\n totalUsers++; // Side effect!\n console.log(users[i]); // Another side effect\n }\n return users;\n}\n\nGood example:
\nfunction activateUsers(users) {\n return users.map(user => ({ ...user, active: true }));\n}\n\n// Usage:\nconst activeUsers = activateUsers(users);\nconsole.log(`Activated: ${activeUsers.length}`);\n\nRemember: pure functions are the foundation of predictable code. If you see mutation during a code review — feel free to write a comment. This is one of the main causes of hard-to-find bugs in JavaScript.
\n\n2. Asynchrony: promises and async/await
\n\nJS is the king of asynchrony, but also the king of callback hell. When reviewing, pay attention to how asynchronous operations are handled. JavaScript code review without analyzing promise chains is a sham.
\n\nRed flags:
\n- \n
- Lack of error handling: No
.catch()ortry/catch. Sooner or later this will crash the application. \n - Nested promises: If you see
.then()inside.then()— it's a reason for refactoring. \n - Forgotten
await: The function is marked asasync, but calls inside are withoutawait. The result is undefined instead of data. \n
Bad example (lack of error handling):
\nasync function fetchUserData(userId) {\n const response = await fetch(`/api/users/${userId}`);\n const data = await response.json();\n return data;\n}\n\nGood example:
\nasync function fetchUserData(userId) {\n try {\n const response = await fetch(`/api/users/${userId}`);\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n return await response.json();\n } catch (error) {\n console.error('Error loading user:', error);\n throw error; // Re-throw, but log\n }\n}\n\nTip for the reviewer: always ask for an explanation of why try/c