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 说明
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执行过程:
- in Sources 面板in找 to 要debug code
- 点击行号设置断点
- 刷 new 页面 or 触发相关operation
- 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;
}
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);