1. best practicesoverview

JavaScript best practices is 指 in JavaScript Development过程in被广泛认可 , able toimprovingcodequality, 可maintenance性 and performance 编码规范 and Developmenttechniques. 遵循best practices可以helpingDevelopment者writing更清晰, 更 high 效, 更 reliable JavaScript code.

本tutorial将介绍 JavaScript Developmentin 各种best practices, including编码规范, performanceoptimization, security性, debugtechniquesetc.方面 in 容.

2. 编码规范

良 good 编码规范 is writing high quality JavaScript code Basics. 以 under is 一些common 编码规范:

2.1 命名规范

// variable and functionusing small 驼峰命名法 const firstName = "张三"; function calculateTotal(price, quantity) { return price * quantity; } // 常量using全 big 写 and under 划线 const MAX_ITERATIONS = 1000; const API_URL = "https://api.example.com"; // classusing big 驼峰命名法 class UserAccount { constructor(name, email) { this.name = name; this.email = email; } } // 私 has variable and methodusing under 划线 before 缀 class Person { constructor(name) { this._name = name; } _privateMethod() { // 私 has method } }

2.2 code风格

// using 2 个 or 4 个空格forindent function example() { // 2 个空格indent if (condition) { // 嵌套indent console.log("Hello"); } } // using单引号 or 双引号保持一致 const name = "张三"; // 推荐: using双引号 // or const name = '张三'; // 推荐: using单引号 // big 括号using if (condition) { // 推荐: big 括号独占一行 console.log("条件 for 真"); } // 分号using const x = 10; // 推荐: using分号 // 行 long 度 // 推荐: 每行不超过 80-120 个字符 const longVariableName = someFunctionWithLongName(param1, param2, param3, param4); // 空行using function calculate() { // function开始 before 空行 let result = 0; // 逻辑块之间 空行 for (let i = 0; i < 10; i++) { result += i; } return result; }

2.3 comment规范

// 单行comment const x = 10; // 初始化variable x // many 行comment /* * 这 is a many 行comment * 用于解释 complex code逻辑 */ // JSDoc comment /** * 计算两个数 and * @param {number} a - 第一个数 * @param {number} b - 第二个数 * @returns {number} 两个数 and */ function add(a, b) { return a + b; } // 特殊comment标记 // TODO: 待completion functions // FIXME: 需要修复 issues // NOTE: important 说明

3. performanceoptimization

JavaScript performanceoptimization is 确保网页加载 fast 速, run流畅 important 因素. 以 under is 一些common performanceoptimizationtechniques:

3.1 reducing DOM operation

// 不推荐: 频繁operation DOM for (let i = 0; i < 1000; i++) { document.getElementById('counter').textContent = i; } // 推荐: 批量operation DOM const counter = document.getElementById('counter'); for (let i = 0; i < 1000; i++) { counter.textContent = i; } // 推荐: usingdocumentation片段 const list = document.getElementById('myList'); const fragment = document.createDocumentFragment(); for (let i = 0; i < 1000; i++) { const li = document.createElement('li'); li.textContent = `Item ${i}`; fragment.appendChild(li); } list.appendChild(fragment);

3.2 memorymanagement

// 避免全局variable // 不推荐 let globalVar = "全局variable"; // 推荐: using局部variable function example() { let localVar = "局部variable"; // using localVar } // 及时清除定时器 const timerId = setInterval(() => { console.log('定时执行'); }, 1000); // 不再需要时清除 clearInterval(timerId); // 清除event监听器 function handleClick() { console.log('点击event'); } element.addEventListener('click', handleClick); // 不再需要时移除 element.removeEventListener('click', handleClick); // 避免循环引用 function createClosure() { const element = document.getElementById('myElement'); // 不推荐: 可能导致循环引用 element.onclick = function() { console.log(element.id); }; } // 推荐: using WeakMap or WeakSet const elementData = new WeakMap(); function createSafeClosure() { const element = document.getElementById('myElement'); elementData.set(element, { clickCount: 0 }); element.onclick = function() { const data = elementData.get(element); data.clickCount++; console.log('点击次数:', data.clickCount); }; }

3.3 code执行optimization

// cache重复计算 值 // 不推荐 function calculate() { for (let i = 0; i < array.length; i++) { // 每次循环都计算 array.length } } // 推荐 function calculate() { const length = array.length; for (let i = 0; i < length; i++) { // usingcache length } } // using适当 循环method // for 于array array.forEach(item => { // processing每个元素 }); // for 于需要提 before 退出 circumstances for (let i = 0; i < array.length; i++) { if (condition) { break; // 提 before 退出 } } // using箭头functionreducing闭package开销 const numbers = [1, 2, 3, 4, 5]; const doubled = numbers.map(num => num * 2); // using Set and Map improvingfindperformance const uniqueValues = new Set(array); const userMap = new Map(); userMap.set('id1', { name: '张三' }); const user = userMap.get('id1'); // O(1) find

4. security性

JavaScript security性 is Development过程in不可忽视 important 因素. 以 under is 一些common securitybest practices:

4.1 防止 XSS 攻击

// 不推荐: 直接插入 HTML const userInput = ''; element.innerHTML = userInput; // dangerous ! // 推荐: using textContent or encodeHTML const userInput = ''; element.textContent = userInput; // security // 推荐: using DOMPurify library const clean = DOMPurify.sanitize(userInput); element.innerHTML = clean; // security

4.2 防止 CSRF 攻击

// 推荐: using CSRF token const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content'); fetch('/api/action', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': csrfToken // package含 CSRF token }, body: JSON.stringify(data) }); // 推荐: check Origin or Referer 头 // server端implementation app.post('/api/action', (req, res) => { const origin = req.headers.origin; if (origin !== 'https://trusted-domain.com') { return res.status(403).send('Forbidden'); } // processingrequest });

4.3 security API 调用

// 推荐: using HTTPS fetch('https://api.example.com/data') // using HTTPS .then(response => response.json()) .then(data => console.log(data)); // 推荐: 不要 in codein硬编码 API key // 不推荐 const API_KEY = 'your-secret-api-key'; // dangerous ! // 推荐: usingenvironmentvariable const API_KEY = process.env.API_KEY; // security // 推荐: using OAuth or JWT for身份verification fetch('https://api.example.com/data', { headers: { 'Authorization': 'Bearer ' + token // usingtoken } });

5. debugtechniques

has 效 debugtechniques可以helpingDevelopment者 fast 速定位 and 解决codein issues. 以 under is 一些常用 JavaScript debugtechniques:

5.1 using控制台

// basiclog console.log('debuginformation'); // 带样式 log console.log('%c important information', 'color: red; font-size: 16px;'); // warning console.warn('warninginformation'); // error console.error('errorinformation'); // information console.info('information'); // debug console.debug('debuginformation'); // 表格 const users = [{ name: '张三', age: 25 }, { name: '李四', age: 30 }]; console.table(users); // group console.group('userinformation'); console.log('姓名: 张三'); console.log('年龄: 25'); console.groupEnd(); // 计时 console.time('operation耗时'); // 执行operation for (let i = 0; i < 1000000; i++) { // operation } console.timeEnd('operation耗时'); // assertion console.assert(condition, '条件不满足时显示'); // 清除控制台 console.clear();

5.2 using断点

in 浏览器Development者toolinusing断点可以更详细地查看code执行过程:

  1. in Sources 面板in找 to 要debug code
  2. 点击行号设置断点
  3. 刷 new 页面 or 触发相关operation
  4. code执行 to 断点时会暂停, 此时可以:
    • 查看variable值
    • 单步执行code
    • check调用栈

5.3 using debugger 语句

function problematicFunction() { let result = 0; // in 这里设置断点 debugger; for (let i = 0; i < 10; i++) { result += i; } return result; } problematicFunction(); // 执行 to debugger 语句时会暂停

6. code组织

良 good code组织可以improvingcode 可maintenance性 and readable 性. 以 under is 一些code组织 best practices:

6.1 module化

// using ES6 module // user.js export class User { constructor(name, email) { this.name = name; this.email = email; } getName() { return this.name; } } // app.js import { User } from './user.js'; const user = new User('张三', 'zhangsan@example.com'); console.log(user.getName()); // using CommonJS module (Node.js) // user.js class User { constructor(name, email) { this.name = name; this.email = email; } } module.exports = User; // app.js const User = require('./user.js'); const user = new User('张三', 'zhangsan@example.com');

6.2 function and method组织

// function应该 short small 精悍, 只做一件事 function calculateTotal(price, quantity) { return price * quantity; } // functionparameter应该控制 in 合理范围 in // 不推荐: parameter过 many function createUser(name, email, age, address, phone, ...) { // processing many 个parameter } // 推荐: usingobjectparameter function createUser(userData) { const { name, email, age, address, phone } = userData; // processingparameter } // 推荐: using默认parameter function createUser(userData = {}) { const defaults = { name: '匿名', age: 18 }; const finalData = { ...defaults, ...userData }; // processingdata } // 推荐: 返回早期 function validateUser(user) { if (!user) { return false; // 早期返回 } if (!user.name) { return false; // 早期返回 } return true; }

6.3 errorprocessing

// 推荐: using try-catch processing可预见 error try { const result = riskyOperation(); console.log(result); } catch (error) { console.error('发生error:', error); // processingerror } // 推荐: using Promise catch method fetch('https://api.example.com/data') .then(response => response.json()) .then(data => console.log(data)) .catch(error => { console.error('request失败:', error); // processingerror }); // 推荐: using async/await and try-catch async function fetchData() { try { const response = await fetch('https://api.example.com/data'); const data = await response.json(); return data; } catch (error) { console.error('request失败:', error); throw error; // 重 new 抛出error } } // 推荐: 自定义errorclass class ValidationError extends Error { constructor(message) { super(message); this.name = 'ValidationError'; } } function validateInput(input) { if (!input) { throw new ValidationError('输入不能 for 空'); } return true; }

7. performanceoptimization

JavaScript performanceoptimization is improving网页加载速度 and run流畅度 important 手段. 以 under is 一些common performanceoptimizationtechniques:

7.1 reducing HTTP request

  • merge CSS and JavaScript file
  • using CSS sprites mergegraph片
  • using字体graph标代替graph片graph标
  • usingdata URI in 联 small 型graph片

7.2 optimizationresource加载

// latency加载非关键 JavaScript // 预加载关键resource // 预连接 // 预获取 // 懒加载graph片 // 懒加载implementation const lazyImages = document.querySelectorAll('.lazy'); if ('IntersectionObserver' in window) { const imageObserver = new IntersectionObserver((entries, observer) => { entries.forEach(entry => { if (entry.isIntersecting) { const image = entry.target; image.src = image.dataset.src; imageObserver.unobserve(image); } }); }); lazyImages.forEach(image => imageObserver.observe(image)); }

7.3 codeoptimization

// using requestAnimationFrame for动画 function animate() { // 动画逻辑 requestAnimationFrame(animate); } requestAnimationFrame(animate); // using Web Workers processing complex 计算 const worker = new Worker('worker.js'); worker.postMessage({ task: 'calculate', data: largeDataSet }); worker.onmessage = function(event) { console.log('计算结果:', event.data); }; // worker.js self.onmessage = function(event) { if (event.data.task === 'calculate') { const result = performComplexCalculation(event.data.data); self.postMessage(result); } }; function performComplexCalculation(data) { // complex 计算 return result; } // using防抖 and 节流 function debounce(func, wait) { let timeout; return function() { const context = this; const args = arguments; clearTimeout(timeout); timeout = setTimeout(() => { func.apply(context, args); }, wait); }; } function throttle(func, limit) { let inThrottle; return function() { const context = this; const args = arguments; if (!inThrottle) { func.apply(context, args); inThrottle = true; setTimeout(() => { inThrottle = false; }, limit); } }; } // 防抖搜索 const searchInput = document.getElementById('search'); searchInput.addEventListener('input', debounce(function() { console.log('搜索:', this.value); // 执行搜索 }, 300)); // 节流滚动 window.addEventListener('scroll', throttle(function() { console.log('滚动位置:', window.scrollY); // 执行滚动相关operation }, 100));

8. test

test is 保证codequality important 手段. 以 under is 一些test best practices:

8.1 单元test

usingtestframeworksuch as Jest, Mocha etc.for单元test:

// using Jest test // sum.js function sum(a, b) { return a + b; } module.exports = sum; // sum.test.js const sum = require('./sum'); test('1 + 2 应该etc.于 3', () => { expect(sum(1, 2)).toBe(3); }); test('负数相加', () => { expect(sum(-1, -2)).toBe(-3); }); test(' and 零相加', () => { expect(sum(5, 0)).toBe(5); }); // runtest // npm test

8.2 集成test

集成testtest many 个component or module之间 交互:

// using Jest for集成test const UserService = require('./userService'); const UserRepository = require('./userRepository'); // mock依赖 jest.mock('./userRepository'); test('creationuser并保存', async () => { // 设置mock UserRepository.save.mockResolvedValue({ id: 1, name: '张三' }); const userService = new UserService(new UserRepository()); const user = await userService.createUser('张三', 'zhangsan@example.com'); expect(user).toEqual({ id: 1, name: '张三' }); expect(UserRepository.save).toHaveBeenCalledWith({ name: '张三', email: 'zhangsan@example.com' }); });

8.3 E2E test

端 to 端 (E2E) testtest整个application 流程:

// using Cypress for E2E test // cypress/integration/user_flow.spec.js describe('user流程', () => { it('应该able toregister new user', () => { cy.visit('/register'); cy.get('input[name="name"]').type('张三'); cy.get('input[name="email"]').type('zhangsan@example.com'); cy.get('input[name="password"]').type('password123'); cy.get('button[type="submit"]').click(); cy.url().should('include', '/dashboard'); cy.contains('欢迎, 张三'); }); it('应该able tologin', () => { cy.visit('/login'); cy.get('input[name="email"]').type('zhangsan@example.com'); cy.get('input[name="password"]').type('password123'); cy.get('button[type="submit"]').click(); cy.url().should('include', '/dashboard'); cy.contains('欢迎, 张三'); }); }); // runtest // npx cypress run

实践case: refactor不良code

under 面 is 一段存 in issues JavaScript code, 请根据best practices for 其forrefactor:

// 不良codeexample var user = { name: '张三', age: 25, email: 'zhangsan@example.com' }; function calculateTotal(price, quantity) { var result = price * quantity; return result; } function processOrder(order) { if (order) { if (order.items) { var total = 0; for (var i = 0; i < order.items.length; i++) { var item = order.items[i]; total += calculateTotal(item.price, item.quantity); } console.log('订单总金额: ' + total); return total; } else { console.log('订单没 has 商品'); return 0; } } else { console.log('订单不存 in '); return 0; } } var order = { items: [ { price: 100, quantity: 2 }, { price: 50, quantity: 3 } ] }; processOrder(order);

refactor after code:

// refactor after code const user = { name: '张三', age: 25, email: 'zhangsan@example.com' }; const calculateTotal = (price, quantity) => price * quantity; const processOrder = (order) => { if (!order) { console.log('订单不存 in '); return 0; } if (!order.items) { console.log('订单没 has 商品'); return 0; } const total = order.items.reduce((sum, item) => { return sum + calculateTotal(item.price, item.quantity); }, 0); console.log(`订单总金额: ${total}`); return total; }; const order = { items: [ { price: 100, quantity: 2 }, { price: 50, quantity: 3 } ] }; processOrder(order);

互动练习: code审查

请审查以 under code, 指出其in issues并提出improvement建议:

// 待审查 code function getUserData(id) { var xhr = new XMLHttpRequest(); xhr.open('GET', 'https://api.example.com/users/' + id, false); xhr.send(); if (xhr.status === 200) { return JSON.parse(xhr.responseText); } else { return null; } } function displayUserInfo(id) { var user = getUserData(id); if (user) { document.getElementById('user-name').innerHTML = user.name; document.getElementById('user-email').innerHTML = user.email; } else { document.getElementById('user-name').innerHTML = 'user不存 in '; } } var userId = prompt('请输入userID:'); displayUserInfo(userId);