Skip to content

现代 JavaScript 开发指南

简介

JavaScript 是 Web 开发的核心语言,也是当今最流行的编程语言之一。从最初的简单脚本语言,到如今的全栈开发语言,JavaScript 已经发展成为一个功能强大、生态丰富的编程语言。本文将全面介绍现代 JavaScript 的核心概念、新特性和最佳实践,帮助开发者掌握这门语言的精髓。

基础概念

1. 变量声明

javascript
// 使用 let 和 const
let count = 0; // 可变变量
const MAX_COUNT = 100; // 不可变常量

// 解构赋值
const [first, second] = [1, 2]; // 数组解构
const { name, age } = { name: 'John', age: 30 }; // 对象解构
const { name: userName, age: userAge } = { name: 'John', age: 30 }; // 重命名

// 剩余参数解构
const [firstItem, ...restItems] = [1, 2, 3, 4, 5];
const { firstName, ...otherInfo } = { firstName: 'John', lastName: 'Doe', age: 30 };

2. 函数

javascript
// 箭头函数
const add = (a, b) => a + b;
const multiply = (a, b) => {
    return a * b;
};

// 默认参数
function greet(name = 'Guest') {
    return `Hello, ${name}!`;
}

// 剩余参数
function sum(...numbers) {
    return numbers.reduce((total, num) => total + num, 0);
}

// 展开运算符
const numbers = [1, 2, 3];
const max = Math.max(...numbers);

// 箭头函数与 this
const person = {
    name: 'John',
    sayHello: function() {
        setTimeout(() => {
            console.log(`Hello, my name is ${this.name}`); // this 指向 person 对象
        }, 1000);
    }
};

3. 模板字符串

javascript
// 基本用法
const name = 'John';
const greeting = `Hello, ${name}!`;

// 多行字符串
const multiLine = `
    This is a
    multi-line
    string
`;

// 表达式
const a = 10;
const b = 20;
const result = `${a} + ${b} = ${a + b}`;

// 标签模板
function highlight(strings, ...values) {
    return strings.reduce((result, string, index) => {
        return result + string + (values[index] ? `<mark>${values[index]}</mark>` : '');
    }, '');
}

const price = 20;
const message = highlight`The price is ${price} dollars`;

4. 数组和对象方法

javascript
// 数组方法
const numbers = [1, 2, 3, 4, 5];

// map: 转换数组
const doubled = numbers.map(n => n * 2);

// filter: 过滤数组
const evenNumbers = numbers.filter(n => n % 2 === 0);

// reduce: 归约数组
const sum = numbers.reduce((acc, curr) => acc + curr, 0);

// find: 查找元素
const found = numbers.find(n => n > 3);

// includes: 检查元素是否存在
const hasThree = numbers.includes(3);

// 对象方法
const person = {
    name: 'John',
    age: 30
};

// Object.keys: 获取对象键
const keys = Object.keys(person);

// Object.values: 获取对象值
const values = Object.values(person);

// Object.entries: 获取键值对
const entries = Object.entries(person);

// Object.assign: 合并对象
const updatedPerson = Object.assign({}, person, { age: 31 });

// 扩展运算符: 合并对象
const newPerson = { ...person, age: 31, city: 'New York' };

现代特性

1. 异步编程

javascript
// Promise 基础
const fetchData = () => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            const success = true;
            if (success) {
                resolve('Data fetched successfully!');
            } else {
                reject('Failed to fetch data');
            }
        }, 1000);
    });
};

// Promise 链式调用
fetchData()
    .then(data => {
        console.log(data);
        return 'Processed data';
    })
    .then(result => {
        console.log(result);
    })
    .catch(error => {
        console.error(error);
    })
    .finally(() => {
        console.log('Operation completed');
    });

// Promise.all: 并行执行多个 Promise
const promise1 = fetch('https://api.example.com/data1');
const promise2 = fetch('https://api.example.com/data2');

Promise.all([promise1, promise2])
    .then(responses => Promise.all(responses.map(res => res.json())))
    .then(data => {
        console.log('All data:', data);
    })
    .catch(error => {
        console.error('Error:', error);
    });

// Async/Await
async function getData() {
    try {
        const result = await fetchData();
        console.log(result);
        
        // 连续 await
        const response = await fetch('https://api.example.com/data');
        const data = await response.json();
        console.log(data);
    } catch (error) {
        console.error('Error:', error);
    } finally {
        console.log('Cleanup');
    }
}

// 异步函数返回 Promise
async function processData() {
    const data = await fetchData();
    return data.toUpperCase();
}

processData().then(result => console.log(result));

2. 模块化

javascript
// ES 模块 - 导出
// helper.js
export const formatDate = (date) => date.toLocaleDateString();
export const validateEmail = (email) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);

export default {
    formatDate,
    validateEmail
};

// ES 模块 - 导入
// main.js
import { formatDate, validateEmail } from './helper.js';
import helper from './helper.js';

// 动态导入
async function loadModule() {
    const module = await import('./helper.js');
    console.log(module.formatDate(new Date()));
}

// CommonJS 模块 (Node.js)
// helper.cjs
module.exports = {
    formatDate: (date) => date.toLocaleDateString(),
    validateEmail: (email) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)
};

// main.cjs
const { formatDate } = require('./helper.cjs');

3. 解构和扩展运算符

javascript
// 数组解构
const [a, b, ...rest] = [1, 2, 3, 4, 5];

// 对象解构
const { name, age, ...other } = { name: 'John', age: 30, city: 'New York', country: 'USA' };

// 函数参数解构
function printUser({ name, age }) {
    console.log(`${name} is ${age} years old`);
}

const user = { name: 'John', age: 30 };
printUser(user);

// 扩展运算符
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const combined = [...arr1, ...arr2];

const obj1 = { a: 1, b: 2 };
const obj2 = { c: 3, d: 4 };
const merged = { ...obj1, ...obj2 };

// 函数参数展开
function sum(a, b, c) {
    return a + b + c;
}

const numbers = [1, 2, 3];
sum(...numbers);

4. 集合类型

javascript
// Set: 无序唯一值集合
const set = new Set([1, 2, 3, 3, 4]);
set.add(5);
set.delete(1);
set.has(2); // true
set.size; // 4

// 遍历 Set
for (const item of set) {
    console.log(item);
}

// Map: 键值对集合
const map = new Map();
map.set('name', 'John');
map.set('age', 30);
map.get('name'); // 'John'
map.has('age'); // true
map.delete('age');
map.size; // 1

// 遍历 Map
for (const [key, value] of map) {
    console.log(`${key}: ${value}`);
}

// WeakSet 和 WeakMap
// 弱引用,不会阻止垃圾回收
const weakSet = new WeakSet();
const weakMap = new WeakMap();

// Symbol: 唯一标识符
const symbol1 = Symbol('description');
const symbol2 = Symbol('description');
console.log(symbol1 === symbol2); // false

// 使用 Symbol 作为对象属性
const obj = {
    [symbol1]: 'value1',
    [symbol2]: 'value2'
};

// BigInt: 大整数
const bigNumber = 1234567890123456789012345678901234567890n;
const anotherBigNumber = BigInt('1234567890123456789012345678901234567890');

5. 现代操作符

javascript
// 可选链操作符 (?.)
const user = {
    name: 'John',
    address: {
        street: '123 Main St'
    }
};

// 安全访问嵌套属性
const street = user?.address?.street;
const zipCode = user?.address?.zipCode; // undefined,不会抛出错误

// 可选链调用函数
const user2 = {
    name: 'Jane',
    sayHello: function() {
        return `Hello, ${this.name}!`;
    }
};

const greeting = user2?.sayHello?.(); // "Hello, Jane!"
const greeting2 = user?.sayHello?.(); // undefined

// 空值合并操作符 (??)
const name = null ?? 'Default Name'; // "Default Name"
const age = 0 ?? 18; // 0 (0 不是 null 或 undefined)
const email = '' ?? 'default@example.com'; // "" (空字符串不是 null 或 undefined)

// 空值赋值操作符 (??=)
let username = null;
username ??= 'Guest'; // "Guest"

let existingUsername = 'John';
existingUsername ??= 'Guest'; // "John" (已有值,不会被覆盖)

// 逻辑或赋值操作符 (||=)
let count = 0;
count ||= 10; // 10 (0 是 falsy 值)

let existingCount = 5;
existingCount ||= 10; // 5 (已有真值,不会被覆盖)

// 逻辑与赋值操作符 (&&=)
let isValid = true;
isValid &&= false; // false

let existingValid = true;
existingValid &&= true; // true

面向对象编程

1. 类

javascript
class Person {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }

    greet() {
        return `Hello, I'm ${this.name}`;
    }

    get fullName() {
        return this.name;
    }

    set fullName(value) {
        this.name = value;
    }

    static create(name, age) {
        return new Person(name, age);
    }
}

class Employee extends Person {
    constructor(name, age, role, salary) {
        super(name, age);
        this.role = role;
        this.salary = salary;
    }

    getDetails() {
        return `${super.greet()}, I work as a ${this.role}`;
    }

    // 重写方法
    greet() {
        return `Hello from Employee: ${this.name}`;
    }
}

// 使用类
const person = new Person('John', 30);
const employee = new Employee('Jane', 25, 'Developer', 80000);
const personFromStatic = Person.create('Bob', 35);

2. 原型继承

javascript
// 构造函数
function Animal(name) {
    this.name = name;
}

// 原型方法
Animal.prototype.speak = function() {
    return `${this.name} makes a sound.`;
};

// 继承
function Dog(name, breed) {
    Animal.call(this, name); // 调用父构造函数
    this.breed = breed;
}

// 设置原型链
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;

// 添加子类方法
Dog.prototype.bark = function() {
    return `${this.name} barks!`;
};

// 重写父类方法
Dog.prototype.speak = function() {
    return `${this.name} woofs!`;
};

// 使用
const dog = new Dog('Rex', 'German Shepherd');
dog.speak(); // "Rex woofs!"
dog.bark(); // "Rex barks!"

3. 混入 (Mixins)

javascript
// 混入对象
const canEat = {
    eat() {
        console.log(`${this.name} is eating`);
    }
};

const canSleep = {
    sleep() {
        console.log(`${this.name} is sleeping`);
    }
};

// 应用混入
class Animal {
    constructor(name) {
        this.name = name;
    }
}

// 合并混入
Object.assign(Animal.prototype, canEat, canSleep);

// 使用
const cat = new Animal('Whiskers');
cat.eat(); // "Whiskers is eating"
cat.sleep(); // "Whiskers is sleeping"

函数式编程

1. 高阶函数

javascript
// 高阶函数:接受或返回函数的函数
function createMultiplier(factor) {
    return function(number) {
        return number * factor;
    };
}

const double = createMultiplier(2);
const triple = createMultiplier(3);

double(5); // 10
triple(5); // 15

// 数组高阶函数
const numbers = [1, 2, 3, 4, 5];

// map: 转换数组
const doubled = numbers.map(n => n * 2);

// filter: 过滤数组
const evenNumbers = numbers.filter(n => n % 2 === 0);

// reduce: 归约数组
const sum = numbers.reduce((acc, curr) => acc + curr, 0);

// find: 查找元素
const firstGreaterThanThree = numbers.find(n => n > 3);

// findIndex: 查找元素索引
const indexOfThree = numbers.findIndex(n => n === 3);

// every: 检查所有元素
const allPositive = numbers.every(n => n > 0);

// some: 检查至少一个元素
const hasEven = numbers.some(n => n % 2 === 0);

// forEach: 遍历数组
numbers.forEach(n => console.log(n));

2. 纯函数

javascript
// 纯函数:相同输入总是产生相同输出,无副作用
function add(a, b) {
    return a + b;
}

function calculateTotal(prices, taxRate) {
    const subtotal = prices.reduce((sum, price) => sum + price, 0);
    return subtotal * (1 + taxRate);
}

// 不纯函数:依赖外部状态或产生副作用
let total = 0;
function addToTotal(n) {
    total += n; // 修改外部状态
    console.log(`Total: ${total}`); // 产生副作用
    return total;
}

// 不纯函数:修改参数
function updateUser(user, newData) {
    user.name = newData.name; // 修改输入参数
    return user;
}

// 纯函数版本:返回新对象
function updateUserPure(user, newData) {
    return { ...user, ...newData };
}

3. 柯里化

javascript
// 柯里化:将多参数函数转换为单参数函数序列
function curry(fn) {
    return function curried(...args) {
        if (args.length >= fn.length) {
            return fn.apply(this, args);
        } else {
            return function(...moreArgs) {
                return curried.apply(this, args.concat(moreArgs));
            };
        }
    };
}

// 示例
function add(a, b, c) {
    return a + b + c;
}

const curriedAdd = curry(add);
const add5 = curriedAdd(5);
const add5And10 = add5(10);
add5And10(15); // 30

// 箭头函数柯里化
const multiply = (a) => (b) => (c) => a * b * c;
const multiplyBy2 = multiply(2);
const multiplyBy2And3 = multiplyBy2(3);
multiplyBy2And3(4); // 24

4. 组合函数

javascript
// 组合:将多个函数组合成一个函数
function compose(...fns) {
    return function(x) {
        return fns.reduceRight((acc, fn) => fn(acc), x);
    };
}

// 管道:从左到右组合函数
function pipe(...fns) {
    return function(x) {
        return fns.reduce((acc, fn) => fn(acc), x);
    };
}

// 示例
const add1 = x => x + 1;
const multiply2 = x => x * 2;
const subtract3 = x => x - 3;

const composed = compose(subtract3, multiply2, add1);
composed(5); // (5 + 1) * 2 - 3 = 9

const piped = pipe(add1, multiply2, subtract3);
piped(5); // (5 + 1) * 2 - 3 = 9

错误处理

1. Try-Catch

javascript
try {
    // 可能抛出错误的代码
    const result = riskyOperation();
    console.log('Operation successful:', result);
} catch (error) {
    console.error('Error occurred:', error.message);
    // 可以根据错误类型进行不同处理
    if (error instanceof TypeError) {
        console.error('Type error:', error);
    } else if (error instanceof RangeError) {
        console.error('Range error:', error);
    }
} finally {
    // 总是执行的代码,用于清理资源
    console.log('Cleanup operations');
}

2. 自定义错误

javascript
class ValidationError extends Error {
    constructor(message, field) {
        super(message);
        this.name = 'ValidationError';
        this.field = field;
    }
}

class AuthenticationError extends Error {
    constructor(message) {
        super(message);
        this.name = 'AuthenticationError';
    }
}

function validateUser(user) {
    if (!user.name) {
        throw new ValidationError('Name is required', 'name');
    }
    if (!user.email) {
        throw new ValidationError('Email is required', 'email');
    }
    if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(user.email)) {
        throw new ValidationError('Invalid email format', 'email');
    }
    return true;
}

function login(username, password) {
    if (username !== 'admin' || password !== 'password') {
        throw new AuthenticationError('Invalid credentials');
    }
    return 'Login successful';
}

// 使用自定义错误
try {
    const user = { name: 'John' };
    validateUser(user);
} catch (error) {
    if (error instanceof ValidationError) {
        console.error(`Validation error in ${error.field}: ${error.message}`);
    } else {
        console.error('Unexpected error:', error);
    }
}

3. Promise 错误处理

javascript
// Promise 错误处理
fetch('https://api.example.com/data')
    .then(response => {
        if (!response.ok) {
            throw new Error(`HTTP error! status: ${response.status}`);
        }
        return response.json();
    })
    .then(data => {
        console.log('Data:', data);
    })
    .catch(error => {
        console.error('Error:', error);
    });

// Async/Await 错误处理
async function fetchData() {
    try {
        const response = await fetch('https://api.example.com/data');
        if (!response.ok) {
            throw new Error(`HTTP error! status: ${response.status}`);
        }
        const data = await response.json();
        console.log('Data:', data);
        return data;
    } catch (error) {
        console.error('Error:', error);
        // 可以重新抛出错误
        throw error;
    }
}

最佳实践

1. 代码组织

  • 使用模块化:将代码分割成多个模块,每个模块负责特定功能
  • 遵循单一职责原则:每个函数或类只负责一个功能
  • 保持代码简洁:避免不必要的复杂性,遵循 KISS 原则
  • 使用有意义的命名:变量、函数和类的名称应该清晰表达其用途
  • 添加注释:为复杂逻辑添加注释,提高代码可读性

2. 性能优化

  • 避免全局变量:减少全局变量的使用,避免命名冲突和内存泄漏
  • 使用事件委托:对于大量相似元素,使用事件委托减少事件监听器数量
  • 实现防抖和节流:对于频繁触发的事件(如滚动、 resize),使用防抖和节流优化
  • 优化循环:减少循环中的计算,避免在循环中操作 DOM
  • 使用适当的数据结构:根据场景选择合适的数据结构,如 Map、Set 等
  • 避免不必要的 DOM 操作:批量处理 DOM 操作,使用 DocumentFragment
  • 使用 requestAnimationFrame:对于动画效果,使用 requestAnimationFrame 代替 setTimeout

3. 安全性

  • 避免 eval:避免使用 eval() 执行字符串代码,防止代码注入攻击
  • 使用严格模式:在脚本顶部添加 'use strict';,提高代码安全性
  • 验证用户输入:对所有用户输入进行验证,防止 XSS 和 SQL 注入攻击
  • 使用 HTTPS:在生产环境中使用 HTTPS,保护数据传输安全
  • 设置适当的 CSP:使用 Content Security Policy 防止 XSS 攻击
  • 避免使用 innerHTML:尽量使用 textContent 或 createElement 代替 innerHTML
  • 使用安全的随机数:使用 crypto.getRandomValues() 生成安全的随机数

4. 代码风格

  • 使用一致的缩进:选择 2 或 4 个空格作为缩进,保持一致
  • 使用分号:虽然 JavaScript 允许省略分号,但为了代码一致性和避免意外行为,建议使用分号
  • 使用单引号或双引号:选择一种引号风格并保持一致
  • 使用箭头函数:对于简短的函数,使用箭头函数提高代码可读性
  • 使用模板字符串:对于复杂的字符串拼接,使用模板字符串
  • 使用解构赋值:对于对象和数组的赋值,使用解构赋值提高代码可读性

工具和框架

1. 包管理

json
{
  "name": "my-project",
  "version": "1.0.0",
  "description": "My JavaScript project",
  "main": "index.js",
  "scripts": {
    "start": "node index.js",
    "dev": "nodemon index.js",
    "test": "jest",
    "lint": "eslint .",
    "build": "webpack"
  },
  "dependencies": {
    "lodash": "^4.17.21",
    "axios": "^1.6.0",
    "express": "^4.18.2"
  },
  "devDependencies": {
    "jest": "^29.7.0",
    "eslint": "^8.55.0",
    "prettier": "^3.1.1",
    "nodemon": "^3.0.2",
    "webpack": "^5.89.0",
    "webpack-cli": "^5.1.4",
    "babel-loader": "^9.1.3",
    "@babel/core": "^7.23.6",
    "@babel/preset-env": "^7.23.6"
  }
}

2. 代码质量工具

ESLint:代码质量检查工具

javascript
// .eslintrc.js
module.exports = {
    env: {
        browser: true,
        es2021: true,
        node: true
    },
    extends: [
        'eslint:recommended',
        'prettier'
    ],
    parserOptions: {
        ecmaVersion: 12,
        sourceType: 'module'
    },
    rules: {
        'no-console': 'warn',
        'no-unused-vars': 'error',
        'prefer-const': 'error'
    }
};

Prettier:代码格式化工具

javascript
// .prettierrc.js
module.exports = {
    semi: true,
    trailingComma: 'es5',
    singleQuote: true,
    printWidth: 80,
    tabWidth: 2
};

3. 构建工具

Webpack:模块打包工具

javascript
// webpack.config.js
const path = require('path');

module.exports = {
    entry: './src/index.js',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'bundle.js'
    },
    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['@babel/preset-env']
                    }
                }
            }
        ]
    },
    devServer: {
        static: {
            directory: path.join(__dirname, 'public')
        },
        port: 3000,
        hot: true
    },
    mode: 'development'
};

Vite:现代前端构建工具

javascript
// vite.config.js
import { defineConfig } from 'vite';

export default defineConfig({
    server: {
        port: 3000
    },
    build: {
        outDir: 'dist',
        minify: 'terser'
    }
});

4. 测试工具

Jest:JavaScript 测试框架

javascript
// sum.test.js
const sum = require('./sum');

test('adds 1 + 2 to equal 3', () => {
    expect(sum(1, 2)).toBe(3);
});

test('adds negative numbers', () => {
    expect(sum(-1, -2)).toBe(-3);
});

Cypress:端到端测试工具

javascript
// cypress/e2e/homepage.cy.js
describe('Homepage', () => {
    it('should load successfully', () => {
        cy.visit('/');
        cy.contains('Welcome to my website');
    });
    
    it('should have a working navigation', () => {
        cy.visit('/');
        cy.get('nav a').contains('About').click();
        cy.url().should('include', '/about');
    });
});

实际应用场景

1. 数据处理

javascript
// 处理 API 响应数据
async function fetchAndProcessData() {
    try {
        const response = await fetch('https://api.example.com/users');
        const users = await response.json();
        
        // 处理数据
        const activeUsers = users
            .filter(user => user.status === 'active')
            .map(user => ({
                id: user.id,
                fullName: `${user.firstName} ${user.lastName}`,
                email: user.email,
                registrationDate: new Date(user.createdAt).toLocaleDateString()
            }))
            .sort((a, b) => new Date(b.registrationDate) - new Date(a.registrationDate));
        
        return activeUsers;
    } catch (error) {
        console.error('Error processing data:', error);
        return [];
    }
}

2. 表单验证

javascript
// 表单验证
function validateForm(formData) {
    const errors = {};
    
    if (!formData.name) {
        errors.name = 'Name is required';
    }
    
    if (!formData.email) {
        errors.email = 'Email is required';
    } else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email)) {
        errors.email = 'Invalid email format';
    }
    
    if (!formData.password) {
        errors.password = 'Password is required';
    } else if (formData.password.length < 8) {
        errors.password = 'Password must be at least 8 characters';
    }
    
    if (formData.password !== formData.confirmPassword) {
        errors.confirmPassword = 'Passwords do not match';
    }
    
    return {
        isValid: Object.keys(errors).length === 0,
        errors
    };
}

// 使用
const formData = {
    name: 'John Doe',
    email: 'john@example.com',
    password: 'password123',
    confirmPassword: 'password123'
};

const validation = validateForm(formData);
if (validation.isValid) {
    console.log('Form is valid, submitting...');
} else {
    console.log('Form errors:', validation.errors);
}

3. 状态管理

javascript
// 简单的状态管理
class Store {
    constructor(initialState) {
        this.state = initialState;
        this.listeners = [];
    }
    
    getState() {
        return this.state;
    }
    
    setState(newState) {
        this.state = { ...this.state, ...newState };
        this.notifyListeners();
    }
    
    subscribe(listener) {
        this.listeners.push(listener);
        return () => {
            this.listeners = this.listeners.filter(l => l !== listener);
        };
    }
    
    notifyListeners() {
        this.listeners.forEach(listener => listener(this.state));
    }
}

// 使用
const initialState = {
    user: null,
    isLoading: false,
    error: null
};

const store = new Store(initialState);

// 订阅状态变化
const unsubscribe = store.subscribe(state => {
    console.log('State changed:', state);
});

// 更新状态
store.setState({ isLoading: true });
store.setState({ user: { name: 'John', email: 'john@example.com' }, isLoading: false });

// 取消订阅
unsubscribe();

设计模式

1. 单例模式

javascript
// 单例模式:确保一个类只有一个实例
class Singleton {
    constructor() {
        if (Singleton.instance) {
            return Singleton.instance;
        }
        this.data = [];
        Singleton.instance = this;
    }
    
    addItem(item) {
        this.data.push(item);
    }
    
    getItem(index) {
        return this.data[index];
    }
    
    static getInstance() {
        if (!Singleton.instance) {
            Singleton.instance = new Singleton();
        }
        return Singleton.instance;
    }
}

// 使用
const instance1 = new Singleton();
const instance2 = new Singleton();
console.log(instance1 === instance2); // true

const instance3 = Singleton.getInstance();
console.log(instance1 === instance3); // true

2. 工厂模式

javascript
// 工厂模式:创建对象的接口,让子类决定实例化哪个类
class Product {
    constructor(name) {
        this.name = name;
    }
    
    display() {
        return `Product: ${this.name}`;
    }
}

class ConcreteProductA extends Product {
    display() {
        return `Concrete Product A: ${this.name}`;
    }
}

class ConcreteProductB extends Product {
    display() {
        return `Concrete Product B: ${this.name}`;
    }
}

class ProductFactory {
    static createProduct(type, name) {
        switch (type) {
            case 'A':
                return new ConcreteProductA(name);
            case 'B':
                return new ConcreteProductB(name);
            default:
                throw new Error('Invalid product type');
        }
    }
}

// 使用
const productA = ProductFactory.createProduct('A', 'Product 1');
const productB = ProductFactory.createProduct('B', 'Product 2');
console.log(productA.display()); // "Concrete Product A: Product 1"
console.log(productB.display()); // "Concrete Product B: Product 2"

3. 观察者模式

javascript
// 观察者模式:定义对象间的一种一对多依赖关系,当一个对象状态改变时,所有依赖它的对象都得到通知并被自动更新
class Subject {
    constructor() {
        this.observers = [];
    }
    
    subscribe(observer) {
        this.observers.push(observer);
    }
    
    unsubscribe(observer) {
        this.observers = this.observers.filter(obs => obs !== observer);
    }
    
    notify(data) {
        this.observers.forEach(observer => observer.update(data));
    }
}

class Observer {
    constructor(name) {
        this.name = name;
    }
    
    update(data) {
        console.log(`${this.name} received update: ${data}`);
    }
}

// 使用
const subject = new Subject();
const observer1 = new Observer('Observer 1');
const observer2 = new Observer('Observer 2');

subject.subscribe(observer1);
subject.subscribe(observer2);

subject.notify('Hello World!');
// Output:
// Observer 1 received update: Hello World!
// Observer 2 received update: Hello World!

subject.unsubscribe(observer1);
subject.notify('Hello Again!');
// Output:
// Observer 2 received update: Hello Again!

4. 装饰器模式

javascript
// 装饰器模式:动态地给对象添加额外的职责
class Component {
    operation() {
        return 'Component operation';
    }
}

class Decorator {
    constructor(component) {
        this.component = component;
    }
    
    operation() {
        return this.component.operation();
    }
}

class ConcreteDecoratorA extends Decorator {
    operation() {
        return `ConcreteDecoratorA(${super.operation()})`;
    }
}

class ConcreteDecoratorB extends Decorator {
    operation() {
        return `ConcreteDecoratorB(${super.operation()})`;
    }
}

// 使用
const component = new Component();
const decoratorA = new ConcreteDecoratorA(component);
const decoratorB = new ConcreteDecoratorB(decoratorA);

console.log(component.operation()); // "Component operation"
console.log(decoratorA.operation()); // "ConcreteDecoratorA(Component operation)"
console.log(decoratorB.operation()); // "ConcreteDecoratorB(ConcreteDecoratorA(Component operation))"

总结

现代 JavaScript 提供了丰富的特性和工具,从 ES6+ 的新语法到强大的异步编程模型,从函数式编程范式到面向对象编程,JavaScript 已经发展成为一门功能强大、灵活多变的编程语言。

通过掌握本文介绍的核心概念和最佳实践,你可以:

  1. 编写更简洁、更可读的代码:使用箭头函数、模板字符串、解构赋值、可选链操作符等现代特性
  2. 处理异步操作更优雅:使用 Promise 和 async/await 简化异步代码
  3. 构建更可维护的应用:使用模块化、单一职责原则、设计模式和良好的代码组织
  4. 提高代码性能:了解性能优化技巧,避免常见的性能陷阱
  5. 增强代码安全性:遵循安全最佳实践,防止常见的安全漏洞
  6. 使用现代数据结构:充分利用 Set、Map、WeakSet、WeakMap 等现代集合类型
  7. 应用设计模式:使用单例、工厂、观察者、装饰器等设计模式解决常见问题

JavaScript 的学习是一个持续的过程,随着 ECMAScript 规范的不断更新,新的特性和最佳实践也在不断涌现。保持学习的态度,不断实践和探索,你将能够充分发挥 JavaScript 的潜力,构建出更加优秀的 Web 应用。

参考资源