Padrões de Codificação JavaScript
Padrões JavaScript
Seção intitulada “Padrões JavaScript”XOOPS segue padrões JavaScript modernos (ES6+) com ênfase em legibilidade e manutenibilidade.
Visão Geral
Seção intitulada “Visão Geral”Padrões JavaScript do XOOPS baseiam-se em:
- ECMAScript 2015+ (ES6 e recursos modernos)
- Guia de Estilo JavaScript Airbnb (adaptado)
- Convenções XOOPS para consistência
- Padrões de acessibilidade (WCAG)
Estrutura de Arquivo
Seção intitulada “Estrutura de Arquivo”Organização de Arquivo
Seção intitulada “Organização de Arquivo”// 1. Comentário de cabeçalho de arquivo/** * XOOPS Módulo - Nome de Recurso * @file Manipula interações de usuário no dashboard * @author Seu Nome <email@example.com> * @copyright 2026 Projeto XOOPS * @license GPL-2.0-or-later */
// 2. Importsimport { Helper } from './helpers.js';import { API } from './api.js';
// 3. Constantesconst DEFAULT_TIMEOUT = 5000;const API_ENDPOINT = '/api/v1';
// 4. Configuração de móduloconst Dashboard = {};
// 5. Funções privadasfunction initializeUI() { // ...}
// 6. Métodos públicosDashboard.init = function () { // ...};
// 7. Exportsexport default Dashboard;Nomenclatura de Arquivo
Seção intitulada “Nomenclatura de Arquivo”// Use minúsculas com hífensdashboard.jsuser-profile.jsform-validator.jsapi-client.js
// Componentes React (PascalCase)UserProfile.jsxFormValidator.jsxDashboard.jsxVariáveis e Constantes
Seção intitulada “Variáveis e Constantes”Declaração de Variável
Seção intitulada “Declaração de Variável”// Use const por padrãoconst maxRetries = 3;const userName = 'John';
// Use let para variáveis que mudamlet currentIndex = 0;
// Evite var (legado)// ❌ var oldStyle = true;
// Const objetos e arrays podem ter conteúdo modificadoconst user = { name: 'John' };user.name = 'Jane'; // ✅ OKuser = {}; // ❌ Erro
const numbers = [1, 2, 3];numbers.push(4); // ✅ OKnumbers = []; // ❌ ErroNomenclatura de Variável
Seção intitulada “Nomenclatura de Variável”// Use nomes descritivosconst userName = 'John'; // ✅const un = 'John'; // ❌
// Variáveis booleanas devem indicar estadoconst isActive = true; // ✅const hasPermission = false; // ✅const canEdit = true; // ✅const active = true; // ❌ Pouco claro
// Arrays devem usar nomes pluraisconst users = ['John', 'Jane'];const userList = ['John', 'Jane'];const items = [];Constantes
Seção intitulada “Constantes”// UPPER_SNAKE_CASE para constantes de nível de móduloconst API_TIMEOUT = 5000;const MAX_RETRIES = 3;const DEFAULT_PAGE_SIZE = 10;
// camelCase para propriedades de objeto (até constantes)const config = { apiTimeout: 5000, maxRetries: 3, defaultPageSize: 10,};Funções
Seção intitulada “Funções”Declaração de Função
Seção intitulada “Declaração de Função”// Funções nomeadas (preferidas para reutilização)function validateEmail(email) { return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);}
// Funções arrow (preferidas para callbacks)const validateEmail = (email) => { return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);};
// Funções arrow curtasconst isPositive = (num) => num > 0;const double = (x) => x * 2;
// Evite expressões de função anônima// ❌ const fn = function() {};Nomenclatura de Função
Seção intitulada “Nomenclatura de Função”// Use nomes descritivos baseados em verbofunction getUserById(id) { } // ✅ Descreve o que pegafunction validateUserInput(data) { } // ✅ Descreve açãofunction formatDate(date) { } // ✅ Descreve transformação
// Evite letras únicas exceto em casos óbvios (loops)function f(x) { } // ❌function fetch() { } // ❌ Conflita com globalParâmetros de Função
Seção intitulada “Parâmetros de Função”// Use nomes de parâmetro clarosfunction addUser(name, email, role = 'user') { // ...}
// Use desestruturação para objetosfunction createPost({ title, content, author, published = false }) { // ...}
// Documente funções complexas/** * Buscar dados de usuário da API * @param {number} userId - O ID de usuário para buscar * @param {Object} options - Configurações opcionais * @param {boolean} options.includeProfile - Incluir dados de perfil * @returns {Promise<Object>} Objeto de dados de usuário */async function fetchUser(userId, options = {}) { const { includeProfile = false } = options; // ...}Classes e Objetos
Seção intitulada “Classes e Objetos”Definição de Classe
Seção intitulada “Definição de Classe”/** * Representa um usuário no sistema */class User { constructor(name, email) { this.name = name; this.email = email; this.id = null; }
/** * Obter nome de exibição do usuário * @returns {string} */ getDisplayName() { return this.name.trim(); }
/** * Validar email do usuário * @returns {boolean} */ isValidEmail() { return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(this.email); }}
// Usoconst user = new User('John Doe', 'john@example.com');console.log(user.getDisplayName());Literais de Objeto
Seção intitulada “Literais de Objeto”// Use shorthand de objetoconst name = 'John';const age = 30;
// Propriedades shorthand (ES6)const person = { name, age, getInfo() { return `${this.name} tem ${this.age} anos`; },};
// Sem shorthand (evitar)// const person = {// name: name,// age: age,// getInfo: function() { }// };Formatação
Seção intitulada “Formatação”Espaçamento e Indentação
Seção intitulada “Espaçamento e Indentação”// Use 2 espaços para indentação (ou 4, seja consistente)function example() { if (true) { console.log('Indentado'); }}
// Espaços ao redor de operadoresconst x = 5 + 3; // ✅const y = 5+3; // ❌const z = isDone ? 'yes' : 'no'; // ✅
// Sem espaço dentro de parêntesesif (condition) { } // ✅if ( condition ) { } // ❌
// Espaço antes de braces de funçãofunction test() { } // ✅function test(){ } // ❌Comprimento de Linha
Seção intitulada “Comprimento de Linha”// Máximo 100 caracteres por linha (ou 120)// Quebre linhas logicamente
// Strings longasconst message = 'Esta é uma mensagem muito longa que ' + 'continua na próxima linha';
// Chamadas de função longasconst result = myFunction( parameter1, parameter2, parameter3);
// Condicionais longasif (condition1 && condition2 && condition3) { // ...}Pontos e Vírgulas
Seção intitulada “Pontos e Vírgulas”// Use pontos e vírgulasconst x = 5; // ✅const y = 10;
// Não confie em inserção automática de ponto e vírgulaconst x = 5 // ❌ Evite confiar nissoStrings
Seção intitulada “Strings”Literais de String
Seção intitulada “Literais de String”// Use aspas simples para consistênciaconst name = 'John'; // ✅
// Ou aspas duplas - apenas seja consistenteconst name = "John";
// Use template literals para interpolaçãoconst greeting = `Olá, ${name}!`; // ✅
// Evite concatenaçãoconst message = 'Olá ' + name; // ❌const message = `Olá ${name}`; // ✅
// Strings multi-linhaconst html = ` <div> <h1>${title}</h1> <p>${content}</p> </div>`;Métodos de Array
Seção intitulada “Métodos de Array”// Prefira métodos de array modernosconst numbers = [1, 2, 3, 4, 5];
// Mapconst doubled = numbers.map(n => n * 2); // ✅// for (let i = 0; i < numbers.length; i++) { } // ❌
// Filterconst evens = numbers.filter(n => n % 2 === 0); // ✅
// Reduceconst sum = numbers.reduce((acc, n) => acc + n, 0); // ✅
// Findconst first = numbers.find(n => n > 3); // ✅
// Some/Everyconst hasEven = numbers.some(n => n % 2 === 0); // ✅const allPositive = numbers.every(n => n > 0); // ✅Desestruturação de Array
Seção intitulada “Desestruturação de Array”// Extrair elementos de arrayconst [first, second, ...rest] = [1, 2, 3, 4, 5];// first = 1, second = 2, rest = [3, 4, 5]
// Pular elementosconst [,, third] = [1, 2, 3];// third = 3
// Usar em parâmetros de funçãofunction processItems([first, second]) { console.log(first, second);}Objetos
Seção intitulada “Objetos”Desestruturação de Objeto
Seção intitulada “Desestruturação de Objeto”// Extrair propriedades de objetoconst user = { name: 'John', email: 'john@example.com' };const { name, email } = user;
// Renomear propriedadesconst { name: userName, email: userEmail } = user;
// Valores padrãoconst { role = 'user' } = user;
// Desestruturação aninhadaconst { user: { name, email } } = response;
// Parâmetros de funçãofunction displayUser({ name, email, role = 'user' }) { console.log(`${name} (${role})`);}Operador Spread
Seção intitulada “Operador Spread”// Copiar arraysconst original = [1, 2, 3];const copy = [...original];
// Mesclar arraysconst merged = [...arr1, ...arr2];
// Copiar objetosconst user = { name: 'John', email: 'john@example.com' };const userCopy = { ...user };
// Mesclar objetosconst merged = { ...defaults, ...options };
// Atualizar propriedadesconst updated = { ...user, email: 'newemail@example.com' };Programação Assíncrona
Seção intitulada “Programação Assíncrona”Promises
Seção intitulada “Promises”// Promise básicaconst promise = new Promise((resolve, reject) => { if (success) { resolve(result); } else { reject(error); }});
// Métodos de PromisePromise.all([p1, p2, p3]) .then(results => console.log(results)) .catch(error => console.error(error));
Promise.race([p1, p2]) .then(result => console.log(result));Async/Await
Seção intitulada “Async/Await”// Preferido para legibilidadeasync function fetchUser(userId) { try { const response = await fetch(`/api/users/${userId}`); if (!response.ok) throw new Error('Usuário não encontrado'); const data = await response.json(); return data; } catch (error) { console.error('Falha ao buscar usuário:', error); throw error; }}
// Usoconst user = await fetchUser(123);
// Múltiplas operaçõesasync function loadDashboard() { const users = await fetchUsers(); const posts = await fetchPosts(); const comments = await fetchComments();
return { users, posts, comments };}Comentários e Documentação
Seção intitulada “Comentários e Documentação”Comentários Inline
Seção intitulada “Comentários Inline”// Explique POR QUE, não O QUEconst result = calculateTotal(items, taxRate); // ✅ Por quê
// ❌ Não explique código óbvioconst x = 5; // Definir x para 5const sum = a + b; // Adicionar a e bComentários JSDoc
Seção intitulada “Comentários JSDoc”/** * Calcular o preço total de itens incluindo imposto * * @param {Array<Object>} items - Array de itens com propriedade price * @param {number} taxRate - Taxa de imposto como decimal (0.1 = 10%) * @returns {number} Preço total incluindo imposto * @throws {Error} Se items não for um array * @example * const total = calculateTotal( * [{ price: 100 }, { price: 50 }], * 0.1 * ); * console.log(total); // 165 */function calculateTotal(items, taxRate = 0) { if (!Array.isArray(items)) { throw new Error('Items deve ser um array'); }
const subtotal = items.reduce((sum, item) => sum + item.price, 0); return subtotal * (1 + taxRate);}Manipulação de Erros
Seção intitulada “Manipulação de Erros”Try/Catch
Seção intitulada “Try/Catch”// Sempre manipule errostry { const result = riskyOperation();} catch (error) { console.error('Operação falhou:', error);} finally { cleanup();}
// Seja específico com errostry { const data = JSON.parse(jsonString);} catch (error) { if (error instanceof SyntaxError) { console.error('JSON inválido'); } else { console.error('Erro desconhecido'); }}Erros Customizados
Seção intitulada “Erros Customizados”class ValidationError extends Error { constructor(message) { super(message); this.name = 'ValidationError'; }}
// Usoif (!isValidEmail(email)) { throw new ValidationError(`Email inválido: ${email}`);}Melhores Práticas Resumidas
Seção intitulada “Melhores Práticas Resumidas”- Use const por padrão
- Use nomes descritivos
- Use funções arrow para callbacks
- Use async/await para promises
- Documente funções complexas
- Cache elementos DOM
- Use delegação de evento
- Escreva funções puras
- Mantenha funções focadas
Não Faça
Seção intitulada “Não Faça”- Use var (legado)
- Use variáveis globais
- Crie funções longas (mais de 50 linhas)
- Aninha código profundamente
- Use eval()
- Use manipuladores de evento inline
- Deixe console.log() em produção
- Crie vazamentos de memória
- Mute parâmetros de função
Ferramentas e Linting
Seção intitulada “Ferramentas e Linting”Configuração ESLint
Seção intitulada “Configuração ESLint”{ "env": { "browser": true, "es2021": true, "node": true }, "extends": ["eslint:recommended"], "rules": { "indent": ["error", 2], "quotes": ["error", "single"], "semi": ["error", "always"], "no-var": "error", "prefer-const": "error" }}Configuração Prettier
Seção intitulada “Configuração Prettier”{ "semi": true, "singleQuote": true, "trailingComma": "es5", "printWidth": 100, "tabWidth": 2}Documentação Relacionada
Seção intitulada “Documentação Relacionada”- Diretrizes CSS
- Código de Conduta
- Fluxo de Contribuição
- Padrões PHP
#xoops #javascript #es6 #coding-standards #best-practices