Best Practices in Modern JavaScript - Part 1
JavaScript is, without a doubt, the most used programming language in the world and has an enormous influence on one of the most important technologies in our daily lives: the Internet. With this power comes great responsibility, and the JavaScript ecosystem has been evolving rapidly, making it difficult to keep up with best practices.
In this article, we'll explore some of the top best practices in modern JavaScript to write cleaner, maintainable, and efficient code.
1. Project rules are the most important thing
Each project may have specific rules to maintain code consistency. These rules will always take precedence over any external recommendations, including those in this article. Before implementing a practice in a project, make sure it is aligned with the established rules and that all team members agree.
2. Use updated JavaScript
JavaScript has evolved tremendously since its creation in 1995. Many old practices you find on the internet may be outdated. Before implementing a technique, verify that it is compatible with the current version of the language.
3. Use let and const instead of var
Although var is still valid, its use is considered obsolete and, in many cases, can introduce bugs that are difficult to trace due to its functional scope. On the other hand, let and const give us a more predictable and safe scope, being limited to the block where they are declared.
When to use let and when to use const?
- Use const whenever a variable does not change its reference or value. This makes your code easier to understand and reduces errors by protecting immutable values.
- Use let if you need to reassign the variable's value in the future, but only in cases where it is necessary.
Golden rule: Use const by default. If you later need to change the value, switch to let.
Practical examples
- const for constant values:
const PI = 3.14159; console.log(PI); // 3.14159 PI = 3; // TypeError: Assignment to constant variable.
- let for changing values:
let count = 0; for (let i = 1; i <= 3; i++) { count += i; } console.log(count); // 6
- Scope comparison (let vs var):
if (true) { let blockScoped = "Solo dentro del bloque"; var functionScoped = "Disponible fuera también"; } console.log(functionScoped); // "Disponible fuera también" console.log(blockScoped); // ReferenceError: blockScoped is not defined
- Avoid problems with loops and callbacks:
With var you can have unexpected behaviors in loops, especially in asynchronous functions:
for (var i = 0; i < 3; i++) { setTimeout(() => console.log(i), 100); // Imprime 3, 3, 3 }
While let fixes this:
const PI = 3.14159; console.log(PI); // 3.14159 PI = 3; // TypeError: Assignment to constant variable.
Replacing var with let and const is not only good practice, but it also helps make your code safer, more readable, and easier to debug. Make the future you thank you.
4. Opt for Classes: Simplicity in JavaScript
Using Function.prototype for object-oriented programming in JavaScript is an older and often error-prone approach. On the contrary, the classes introduced in ES6 offer a more intuitive syntax that is closer to other object-oriented languages, facilitating the readability and maintenance of the code.
Example with classes (modern and clear):
let count = 0; for (let i = 1; i <= 3; i++) { count += i; } console.log(count); // 6
Comparison with Function.prototype (complicated and less intuitive):
if (true) { let blockScoped = "Solo dentro del bloque"; var functionScoped = "Disponible fuera también"; } console.log(functionScoped); // "Disponible fuera también" console.log(blockScoped); // ReferenceError: blockScoped is not defined
As you can see, the prototype-based approach requires more steps to define methods and can be more confusing for less experienced developers. Not only are classes easier to read, but they also promote cleaner, more modular code.
Why use classes?
- More readable and less prone to errors.
- They facilitate inheritance with extends and the use of super.
- More compatible with modern tools and ES6 standards.
5. Use Real Private Fields in JavaScript
For a long time, JavaScript developers used conventions like an underscore (_) to simulate private fields in classes. However, this was just a visual convention, as the properties were still accessible from outside the class. Now, thanks to real private fields, we can guarantee that certain properties are completely inaccessible from the outside.
⚠️ Attention: This feature may not be available in the console of some browsers.
Why use real private fields?
- Authentic Encapsulation: Protect your data and ensure that it cannot be accessed or modified outside the context of the class.
- Readability: Using the # prefix makes it clear which properties are private, improving code understanding.
- Data security: Prevent accidental errors or unintentional access to internal properties.
Basic example:
for (var i = 0; i < 3; i++) { setTimeout(() => console.log(i), 100); // Imprime 3, 3, 3 }
Advanced Example: Protected Counters
Imagine that you want to create a class that records the number of visits to a page, but you don't want anyone to be able to manipulate that counter directly.
const PI = 3.14159; console.log(PI); // 3.14159 PI = 3; // TypeError: Assignment to constant variable.
In this case, the #visits counter is completely protected from external access, which guarantees that its value is not improperly manipulated.
Considerations
- Private fields cannot be accessed even by subclasses.
- If you need to interact with private data in inheritances, consider using protected methods instead of private fields.
6. Use arrow functions
arrow functions are a modern and elegant way to write functions in JavaScript. They offer a shorter syntax and, unlike traditional functions, automatically inherit the context of this, which avoids common problems in object-oriented programming.
They are especially useful in higher order functions like map, filter and reduce, where we need to pass functions as arguments.
Why use arrow functions?
- Shorter, cleaner syntax: Ideal for keeping code more readable.
- Context of this automatic: Perfect to avoid errors in callbacks or methods.
- Ideal use in inline functions: Like the ones we use in map, filter or events.
Practical examples
1. With map to transform arrays
let count = 0; for (let i = 1; i <= 3; i++) { count += i; } console.log(count); // 6
2. With filter to filter elements
if (true) { let blockScoped = "Solo dentro del bloque"; var functionScoped = "Disponible fuera también"; } console.log(functionScoped); // "Disponible fuera también" console.log(blockScoped); // ReferenceError: blockScoped is not defined
3. With reduce to add values
for (var i = 0; i < 3; i++) { setTimeout(() => console.log(i), 100); // Imprime 3, 3, 3 }
4. In DOM events (be careful with the context!)
When we use arrow functions in events, the this context will not change, which can be useful:
for (let i = 0; i < 3; i++) { setTimeout(() => console.log(i), 100); // Imprime 0, 1, 2 }
Tip: when to not use them
Although arrow functions are great, they are not ideal for everything. Avoid them in cases where you need to access the function context itself, such as in functions that use dynamic this or if you need to write methods in prototypes.
Example where a normal function is better:
class Persona { constructor(nombre) { this.nombre = nombre; } obtenerNombre() { return this.nombre; } } const persona = new Persona('Juan'); console.log(persona.obtenerNombre()); // 'Juan'
If you changed print to an arrow function, you would lose the context of this.
Let's improve that section! I added some context, a clearer explanation, and some additional examples to make it more complete and useful.
7. Null coalescence operator (??)
The null coalescence operator (??) is a more precise alternative to the logical operator || to assign default values. While || considers "falsy" to be values such as 0, false or "", the operator ?? only evaluates null or undefined as "missing" values. This makes it a safer and more specific option in many cases.
What is the key difference?
With ||, any "falsy" value will be replaced by the default value.
With ??, only replaces values that are null or undefined. This allows you to keep "falsy" values like 0 or "" if they are valid in your context.
Basic example:
const PI = 3.14159; console.log(PI); // 3.14159 PI = 3; // TypeError: Assignment to constant variable.
On the other hand, with ||:
let count = 0; for (let i = 1; i <= 3; i++) { count += i; } console.log(count); // 6
Practical cases with ??
- Set default values without overwriting valid values:
if (true) { let blockScoped = "Solo dentro del bloque"; var functionScoped = "Disponible fuera también"; } console.log(functionScoped); // "Disponible fuera también" console.log(blockScoped); // ReferenceError: blockScoped is not defined
- Validate optional configuration:
Suppose you have a system that allows you to customize options:
for (var i = 0; i < 3; i++) { setTimeout(() => console.log(i), 100); // Imprime 3, 3, 3 }
- Avoid errors when working with optional properties:
for (let i = 0; i < 3; i++) { setTimeout(() => console.log(i), 100); // Imprime 0, 1, 2 }
The above is the detailed content of Best Practices in Modern JavaScript - Part 1. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics











The latest trends in JavaScript include the rise of TypeScript, the popularity of modern frameworks and libraries, and the application of WebAssembly. Future prospects cover more powerful type systems, the development of server-side JavaScript, the expansion of artificial intelligence and machine learning, and the potential of IoT and edge computing.

Different JavaScript engines have different effects when parsing and executing JavaScript code, because the implementation principles and optimization strategies of each engine differ. 1. Lexical analysis: convert source code into lexical unit. 2. Grammar analysis: Generate an abstract syntax tree. 3. Optimization and compilation: Generate machine code through the JIT compiler. 4. Execute: Run the machine code. V8 engine optimizes through instant compilation and hidden class, SpiderMonkey uses a type inference system, resulting in different performance performance on the same code.

Python is more suitable for beginners, with a smooth learning curve and concise syntax; JavaScript is suitable for front-end development, with a steep learning curve and flexible syntax. 1. Python syntax is intuitive and suitable for data science and back-end development. 2. JavaScript is flexible and widely used in front-end and server-side programming.

JavaScript is the core language of modern web development and is widely used for its diversity and flexibility. 1) Front-end development: build dynamic web pages and single-page applications through DOM operations and modern frameworks (such as React, Vue.js, Angular). 2) Server-side development: Node.js uses a non-blocking I/O model to handle high concurrency and real-time applications. 3) Mobile and desktop application development: cross-platform development is realized through ReactNative and Electron to improve development efficiency.

This article demonstrates frontend integration with a backend secured by Permit, building a functional EdTech SaaS application using Next.js. The frontend fetches user permissions to control UI visibility and ensures API requests adhere to role-base

I built a functional multi-tenant SaaS application (an EdTech app) with your everyday tech tool and you can do the same. First, what’s a multi-tenant SaaS application? Multi-tenant SaaS applications let you serve multiple customers from a sing

The shift from C/C to JavaScript requires adapting to dynamic typing, garbage collection and asynchronous programming. 1) C/C is a statically typed language that requires manual memory management, while JavaScript is dynamically typed and garbage collection is automatically processed. 2) C/C needs to be compiled into machine code, while JavaScript is an interpreted language. 3) JavaScript introduces concepts such as closures, prototype chains and Promise, which enhances flexibility and asynchronous programming capabilities.

The main uses of JavaScript in web development include client interaction, form verification and asynchronous communication. 1) Dynamic content update and user interaction through DOM operations; 2) Client verification is carried out before the user submits data to improve the user experience; 3) Refreshless communication with the server is achieved through AJAX technology.
