当前位置: 首页 > news >正文

0321美团实习面试——技能大致内容

专业技能

1.掌握盒⼦模型,Flex响应式布局和BFC等问题
盒⼦模型

在这里插入图片描述

Flex布局

在这里插入图片描述

媒体查询

在这里插入图片描述
结合Handleresize.ts监听设备
在这里插入图片描述

BFC

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.掌握原型链,异步,事件循环和闭包等问题
原型链

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

异步

在这里插入图片描述


class Promise {
  static resolve(value) {
    if (value instanceof Promise) {
      return value;
    }
    return new Promise((resolve) => {
      resolve(value);
    });
  }

  static reject(reason) {
    return new Promise((_, reject) => {
      reject(reason);
    });
  }

  static race(promises) {
    return new Promise((resolve, reject) => {
      promises.forEach((promise) => {
        Promise.resolve(promise).then(resolve, reject);
      });
    });
  }

  static all(promises) {
    return new Promise((resolve, reject) => {
      const results = [];
      let completedCount = 0;

      if (promises.length === 0) {
        resolve(results);
        return;
      }

      promises.forEach((promise, index) => {
        Promise.resolve(promise).then(
          (value) => {
            results[index] = value;
            completedCount++;
            if (completedCount === promises.length) {
              resolve(results);
            }
          },
          (reason) => {
            reject(reason);
          }
        );
      });
    });
  }

  constructor(executor) {
    // 状态
    this.status = "pending";
    // 成功结果
    this.value = undefined;
    // 失败原因
    this.reason = undefined;
    // 成功回调函数队列
    this.onResolvedCallbacks = [];
    // 失败回调函数队列
    this.onRejectedCallbacks = [];

    let resolve = (value) => {
      if (this.status === "pending") {
        // 新的值需要是 Promise,则递归解析
        if (value instanceof Promise) {
          return value.then(resolve, reject);
        }
        this.status = "fulfilled";
        this.value = value;
        // 异步执行所有成功回调
        this.onResolvedCallbacks.forEach((fn) => fn());
      }
    };

    let reject = (reason) => {
      if (this.status === "pending") {
        this.status = "rejected";
        this.reason = reason;
        // 异步执行所有失败回调
        this.onRejectedCallbacks.forEach((fn) => fn());
      }
    };
    // 执行器本身错误,直接 reject
    try {
      executor(resolve, reject);
    } catch (error) {
      reject(error);
    }
  }

  then(onFulfilled, onRejected) {
    onFulfilled = typeof onFulfilled === "function" ? onFulfilled : (value) => value;
    onRejected = typeof onRejected === "function" ? onRejected : (reason) => {
      throw reason;
    };
    let context = this;

    return new Promise((resolve, reject) => {
      function handleOnFulfilled() {
        try {
          const result = onFulfilled(context.value);
          if (result instanceof Promise) {
            result.then(resolve, reject);
          } else {
            resolve(result);
          }
        } catch (error) {
          reject(error);
        }
      }

      function handleOnRejected() {
        try {
          const result = onRejected(context.reason);
          if (result instanceof Promise) {
            result.then(resolve, reject);
          } else {
            resolve(result);
          }
        } catch (error) {
          reject(error);
        }
      }

      if (this.status === "fulfilled") {
        setTimeout(() => {
          handleOnFulfilled();
        }, 0);
      }
      if (this.status === "rejected") {
        setTimeout(() => {
          handleOnRejected();
        }, 0);
      }
      // 当状态为 pending 时
      if (this.status === "pending") {
        // onFulfilled 传入到成功数组
        this.onResolvedCallbacks.push(handleOnFulfilled);
        // onRejected 传入到失败数组
        this.onRejectedCallbacks.push(handleOnRejected);
      }
    });
  }

  catch(onRejected) {
    return this.then(null, onRejected);
  }

  finally(onFinally) {
    return this.then(
      (value) => Promise.resolve(onFinally()).then(() => value),
      (reason) => Promise.resolve(onFinally()).then(() => {
        throw reason;
      })
    );
  }
}

事件循环

在这里插入图片描述

class EventLoop {
  constructor() {
    this.callStack = [];
    this.taskQueue = [];
    this.microtaskQueue = [];
  }

  run() {
    while (this.callStack.length > 0 || this.taskQueue.length > 0 || this.microtaskQueue.length > 0) {
      // 执行同步代码
      while (this.callStack.length > 0) {
        const task = this.callStack.pop();
        task();
      }

      // 执行微任务
      while (this.microtaskQueue.length > 0) {
        const microtask = this.microtaskQueue.shift();
        microtask();
      }

      // 执行宏任务
      if (this.taskQueue.length > 0) {
        const task = this.taskQueue.shift();
        task();
      }
    }
  }
}
闭包

在这里插入图片描述

const counterModule = (function() {
  let count = 0; // 私有变量

  return {
    increment: function() {
      count++;
      console.log(count);
    },
    reset: function() {
      count = 0;
      console.log('计数器已重置');
    }
  };
})();

counterModule.increment(); // 1
counterModule.increment(); // 2
counterModule.reset(); // 计数器已重置
3. 掌握Promise、⽣成器、类、接⼝和装饰器等问题

ES6 引入了许多新特性,包括 let 和 const 声明、箭头函数、模板字符串、解构赋值、默认参数、模块化、Promise、Class、Symbol、Set/Map 等,极大地提升了 JavaScript 的语法简洁性、功能性和开发效率。
TypeScript 是 JavaScript 的超集,通过添加静态类型检查、接口、泛型、枚举等特性,增强了代码的可读性、可维护性和开发效率,同时保持了与 JavaScript 的完全兼容
ES6 新特性的使用场景和优缺点、TypeScript 的类型系统、接口与类的区别、泛型的应用、模块化设计,以及两者如何结合提升开发体验和代码质量。

Promise

在这里插入图片描述

const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    const success = true;
    if (success) {
      resolve('操作成功');
    } else {
      reject('操作失败');
    }
  }, 1000);
});

promise
  .then((result) => console.log(result)) // 操作成功
  .catch((error) => console.error(error)); // 操作失败
```”

---

### 4. ​**Promise 的链式调用**
“Promise 支持链式调用,通过 `then` 方法处理成功的结果,通过 `catch` 方法处理失败的情况,还可以使用 `finally` 方法在 Promise 结束后执行清理操作。例如:
```javascript
fetch('https://api.example.com/data')
  .then((response) => response.json())
  .then((data) => console.log(data))
  .catch((error) => console.error('请求失败', error))
  .finally(() => console.log('请求结束'));
```”

---

### 5. ​**Promise 的静态方法**
“Promise 提供了多个静态方法,用于处理多个异步操作:
1. ​**Promise.all**:等待所有 Promise 成功,返回结果数组;如果有一个失败,立即返回失败原因。
2. ​**Promise.race**:返回第一个完成的 Promise 的结果(无论成功或失败)。
3. ​**Promise.allSettled**:等待所有 Promise 完成,返回每个 Promise 的结果和状态。
4. ​**Promise.any**:返回第一个成功的 Promise 的结果;如果全部失败,返回 AggregateError。
例如:
```javascript
const p1 = Promise.resolve('成功1');
const p2 = Promise.reject('失败2');

Promise.all([p1, p2])
  .then((results) => console.log(results))
  .catch((error) => console.error(error)); // 失败2
```”

---

### 6. ​**Promise 的应用场景**
“Promise 在前端开发中有广泛的应用场景,比如:
1. ​**网络请求**:通过 `fetch``axios` 发送异步请求。
2. ​**定时任务**:通过 `setTimeout``setInterval` 实现延时操作。
3. ​**文件操作**:在 Node.js 中,通过 Promise 封装文件读写操作。
4. ​**并发控制**:通过 `Promise.all` 实现多个异步任务的并发执行。”

---

### 7. ​**Promise 的注意事项**
“在使用 Promise 时,需要注意以下几点:
1. ​**错误处理**:确保每个 Promise 链都有 `catch` 方法,避免未捕获的错误。
2. ​**性能问题**:过多的 Promise 嵌套可能导致性能问题,可以通过 `async/await` 优化。
3. ​**状态不可逆**:Promise 的状态一旦改变,就不可再变,确保逻辑正确。”

---

### 8. ​**与 Async/Await 的关系**
“Async/Await 是 Promise 的语法糖,它让异步代码看起来像同步代码,更易读。例如:
```javascript
async function fetchData() {
  try {
    const response = await fetch('https://api.example.com/data');
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error('请求失败', error);
  }
}
```”

---

### 9. ​**总结**
“Promise 是 JavaScript 中处理异步操作的核心机制,通过链式调用和静态方法,可以优雅地处理复杂的异步逻辑。结合 Async/Await,可以进一步提升代码的可读性和可维护性。”

---

### 10. ​**扩展与练习**
“为了加深理解,我平时会通过手写 Promise、实现并发控制等方式来练习。比如,手写一个简单的 Promise:
```javascript
class MyPromise {
  constructor(executor) {
    this.state = 'pending';
    this.value = null;
    this.onFulfilledCallbacks = [];
    this.onRejectedCallbacks = [];

    const resolve = (value) => {
      if (this.state === 'pending') {
        this.state = 'fulfilled';
        this.value = value;
        this.onFulfilledCallbacks.forEach((fn) => fn());
      }
    };

    const reject = (reason) => {
      if (this.state === 'pending') {
        this.state = 'rejected';
        this.value = reason;
        this.onRejectedCallbacks.forEach((fn) => fn());
      }
    };

    try {
      executor(resolve, reject);
    } catch (error) {
      reject(error);
    }
  }

  then(onFulfilled, onRejected) {
    if (this.state === 'fulfilled') {
      onFulfilled(this.value);
    } else if (this.state === 'rejected') {
      onRejected(this.value);
    } else {
      this.onFulfilledCallbacks.push(() => onFulfilled(this.value));
      this.onRejectedCallbacks.push(() => onRejected(this.value));
    }
  }
}
⽣成器

在这里插入图片描述

function* generator() {
  yield 1;
  yield 2;
  return 3;
}

const gen = generator();
console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next()); // { value: 2, done: false }
console.log(gen.next()); // { value: 3, done: true }

  1. 生成器的特点
    “生成器具有以下特点:
  2. 暂停和恢复:通过 yield 暂停执行,通过 next() 恢复执行。
  3. 惰性求值:生成器函数不会一次性执行完所有代码,而是按需执行。
  4. 双向通信:可以通过 next(value) 向生成器传递值,通过 yield 返回值。”

  1. 生成器的应用场景
    “生成器在前端开发中有多种应用场景,比如:
  2. 异步操作:通过生成器实现类似 async/await 的异步控制流。
  3. 迭代器:生成器可以轻松实现自定义迭代器,用于遍历复杂数据结构。
  4. 状态机:生成器适合实现状态机,管理复杂的业务逻辑。
  5. 数据流处理:生成器可以用于处理数据流,比如分批次读取文件。”

  1. 生成器与异步操作
    “生成器可以通过 yield 暂停执行,结合 Promise 可以实现类似 async/await 的效果。例如:
function* fetchData() {
  const response = yield fetch('https://api.example.com/data');
  const data = yield response.json();
  return data;
}

function run(generator) {
  const gen = generator();

  function handle(result) {
    if (result.done) return result.value;
    return Promise.resolve(result.value).then((res) => handle(gen.next(res)));
  }

  return handle(gen.next());
}

run(fetchData).then((data) => console.log(data));
```”

---

### 6. ​**生成器的注意事项**
“在使用生成器时,需要注意以下几点:
1. ​**性能问题**:生成器的暂停和恢复机制可能带来额外的性能开销。
2. ​**调试难度**:生成器的执行流程较复杂,可能增加调试难度。
3. ​**兼容性**:虽然现代浏览器支持生成器,但在旧环境中可能需要使用 Babel 转译。”

---

### 7. ​**生成器与迭代器的关系**
“生成器是迭代器的一种实现方式。通过 `yield` 关键字,生成器可以轻松实现 `Iterator` 接口。例如:
```javascript
const obj = {
  *[Symbol.iterator]() {
    yield 1;
    yield 2;
    yield 3;
  },
};

for (const value of obj) {
  console.log(value); // 1, 2, 3
}
```”

---

### 8. ​**总结**
“生成器是 JavaScript 中一种强大的工具,通过 `yield``next()` 实现了暂停和恢复执行的功能。它非常适合处理异步操作、自定义迭代器以及复杂的数据流。理解生成器有助于编写更灵活、更高效的代码。”

---

### 9. ​**扩展与练习**
“为了加深理解,我平时会通过手写生成器、实现异步控制流等方式来练习。比如,手写一个简单的生成器示例:
```javascript
function* fibonacci() {
  let [prev, curr] = [0, 1];
  while (true) {
    yield curr;
    [prev, curr] = [curr, prev + curr];
  }
}

const gen = fibonacci();
console.log(gen.next().value); // 1
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
console.log(gen.next().value); // 3

在这里插入图片描述

接口

在这里插入图片描述

interface User {
  name: string;
  age: number;
  greet(): void;
}
```”

---

### 3. ​**接口的基本用法**
“接口可以用于定义对象的形状、函数的参数和返回值等。例如:
```typescript
interface Person {
  name: string;
  age: number;
}

const user: Person = {
  name: 'Alice',
  age: 25,
};
```”

---

### 4. ​**接口的扩展**
“接口可以通过 `extends` 关键字继承其他接口,形成更复杂的结构。例如:
```typescript
interface Animal {
  name: string;
}

interface Dog extends Animal {
  breed: string;
}

const dog: Dog = {
  name: 'Buddy',
  breed: 'Golden Retriever',
};
```”

---

### 5. ​**接口的可选属性和只读属性**
“接口支持可选属性和只读属性:
1. ​**可选属性**:通过 `?` 标记,表示属性可以不存在。
2. ​**只读属性**:通过 `readonly` 标记,表示属性不可修改。
例如:
```typescript
interface Config {
  readonly id: number;
  name?: string;
}

const config: Config = {
  id: 1,
};
```”

---

### 6. ​**接口与类型的区别**
“接口和类型别名(`type`)都可以定义对象结构,但有以下区别:
1. ​**扩展性**:接口可以通过 `extends` 继承,类型别名需要通过 `&` 合并。
2. ​**重复声明**:接口可以重复声明,属性会自动合并;类型别名不可重复声明。
例如:
```typescript
interface User {
  name: string;
}

interface User {
  age: number;
}

const user: User = {
  name: 'Alice',
  age: 25,
};
```”

---

### 7. ​**接口的应用场景**
“接口在前端开发中有多种应用场景,比如:
1. ​**定义对象结构**:约束对象的属性和方法。
2. ​**函数参数和返回值**:明确函数的输入和输出类型。
3. ​**类实现接口**:通过 `implements` 关键字让类遵循接口的结构。
例如:
```typescript
interface Vehicle {
  start(): void;
  stop(): void;
}

class Car implements Vehicle {
  start() {
    console.log('Car started');
  }
  stop() {
    console.log('Car stopped');
  }
}
```”

---

### 8. ​**总结**
“TypeScript 的接口是一种强大的工具,用于定义对象的结构和行为。它通过类型检查提高了代码的可靠性和可维护性,同时支持扩展、可选属性和只读属性等功能。理解接口的使用场景和最佳实践,有助于编写更健壮的类型化代码。”

---

### 9. ​**潜在问题与答案**
#### ​**Q1: 接口和类型别名有什么区别?**
- ​**A1**: 接口和类型别名都可以定义对象结构,但接口支持继承(`extends`)和重复声明,而类型别名需要通过 `&` 合并且不可重复声明。接口更适合定义对象结构,类型别名更适合定义联合类型或复杂类型。

#### ​**Q2: 如何让一个类实现多个接口?**
- ​**A2**: 可以通过 `implements` 关键字让类实现多个接口,例如:
```typescript
interface A {
  methodA(): void;
}

interface B {
  methodB(): void;
}

class C implements A, B {
  methodA() {}
  methodB() {}
}

在这里插入图片描述
在这里插入图片描述

装饰器

在这里插入图片描述

function log(target: any, key: string, descriptor: PropertyDescriptor) {
  console.log(`Called ${key}`);
}

class MyClass {
  @log
  myMethod() {
    console.log('Executing myMethod');
  }
}
```”

---

### 3. ​**装饰器的类型**
“装饰器可以分为以下几种类型:
1. ​**类装饰器**:用于修改或扩展类的行为。
2. ​**方法装饰器**:用于修改或扩展方法的行为。
3. ​**属性装饰器**:用于修改或扩展属性的行为。
4. ​**参数装饰器**:用于修改或扩展参数的行为。
5. ​**访问器装饰器**:用于修改或扩展 `getter``setter` 的行为。”

---

### 4. ​**装饰器的基本用法**
“装饰器通过 `@` 符号使用,可以应用于类、方法、属性或参数。例如:
```typescript
function classDecorator(constructor: Function) {
  console.log('Class decorator');
}

function methodDecorator(target: any, key: string, descriptor: PropertyDescriptor) {
  console.log('Method decorator');
}

@classDecorator
class MyClass {
  @methodDecorator
  myMethod() {}
}
```”

---

### 5. ​**装饰器的应用场景**
“装饰器在前端开发中有多种应用场景,比如:
1. ​**日志记录**:通过装饰器自动记录方法的调用信息。
2. ​**权限校验**:通过装饰器验证用户权限。
3. ​**性能监控**:通过装饰器统计方法的执行时间。
4. ​**依赖注入**:通过装饰器实现依赖注入机制。
5. ​**表单验证**:通过装饰器验证表单字段。”

---

### 6. ​**装饰器的注意事项**
“在使用装饰器时,需要注意以下几点:
1. ​**实验性特性**:装饰器目前是实验性特性,未来可能会发生变化。
2. ​**性能开销**:装饰器可能会带来额外的性能开销,尤其是在复杂的应用中。
3. ​**调试难度**:装饰器的执行顺序和逻辑可能增加调试难度。”

---

### 7. ​**总结**
“TypeScript 装饰器是一种强大的工具,通过为类、方法、属性或参数添加元数据和额外功能,可以显著提高代码的可读性和可维护性。理解装饰器的使用场景和最佳实践,有助于编写更灵活、更高效的代码。”

---

### 8. ​**潜在问题与答案**
#### ​**Q1: 装饰器的执行顺序是怎样的?**
- ​**A1**: 装饰器的执行顺序遵循以下规则:
  1. ​**参数装饰器**:从最后一个参数开始执行。
  2. ​**方法/属性/访问器装饰器**:从下往上执行。
  3. ​**类装饰器**:从上往下执行。
  例如:
  ```typescript
  function decoratorA() {
    console.log('A');
  }

  function decoratorB() {
    console.log('B');
  }

  @decoratorA
  @decoratorB
  class MyClass {} // 输出:B, A

在这里插入图片描述
在这里插入图片描述

泛型

在这里插入图片描述

4.了解React Fiber架构 以及Vue响应式和DIFF算法
React Fiber架构

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

React DIFF

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Vue2&3响应式

响应式原理
在这里插入图片描述

在这里插入图片描述
数据劫持
Vue2 Object.defineProperty()

const data = { count: 0 };

// 劫持属性
Object.defineProperty(data, "count", {
  get() {
    console.log("读取 count");
    return this._count; // 使用临时变量存储值
  },
  set(newVal) {
    console.log("修改 count");
    this._count = newVal;
  }
});

data.count = 1; // 输出 "修改 count"
console.log(data.count); // 输出 "读取 count" → 1


// 依赖收集器(Dep类)
class Dep {
  constructor() {
    this.subs = []; // 存储所有Watcher(订阅者)
  }
  addSub(watcher) {
    this.subs.push(watcher);
  }
  notify() {
    this.subs.forEach(watcher => watcher.update());
  }
}

// 观察者(Watcher类)
class Watcher {
  constructor(data, key, callback) {
  //	Dep类的静态属性
    Dep.target = this; // 当前Watcher实例
    this.callback = callback;
    //data[key]触发getter,且此时Dep.target不为空,将进行依赖收集
    this.value = data[key]; // 触发属性的getter,完成依赖收集
    Dep.target = null;
  }
  update() {
    this.callback(this.value); // 数据变化时触发回调
  }
}

// 数据劫持:将对象属性转为响应式
function defineReactive(obj, key, val) {
  const dep = new Dep(); // 每个属性对应一个Dep实例
  Object.defineProperty(obj, key, {
    get() {
      if (Dep.target) {
        dep.addSub(Dep.target); // 收集当前Watcher到Dep[[13]]
      }
      return val;
    },
    set(newVal) {
      if (newVal === val) return;
      val = newVal;
      dep.notify(); // 数据变化时通知所有订阅者[[18]]
    }
  });
}

// 示例使用
const data = { count: 0 };
defineReactive(data, 'count', data.count);

new Watcher(data, 'count', (newVal) => {
  console.log('视图更新:', newVal);
});

data.count = 1; // 输出:视图更新: 1


Vue3 Proxy

const data = { count: 0 };

const proxy = new Proxy(data, {
  get(target, prop) {
    console.log(`读取 ${prop}`);
    return Reflect.get(target, prop);
  },
  set(target, prop, value) {
    console.log(`修改 ${prop}${value}`);
    return Reflect.set(target, prop, value);
  }
});

proxy.count = 1; // 输出 "修改 count 为 1"
console.log(proxy.count); // 输出 "读取 count" → 1

// 依赖收集器(Dep类同上)
class Dep {
  constructor() {
    this.subs = []; // 存储所有Watcher(订阅者)
  }
  addSub(watcher) {
    this.subs.push(watcher);
  }
  notify() {
    this.subs.forEach(watcher => watcher.update());
  }
}

// 观察者(Watcher类)
class Watcher {
  constructor(data, key, callback) {
  // Dep类的静态属性
    Dep.target = this; // 当前Watcher实例
    this.callback = callback;
    //data[key]触发getter,且此时Dep.target不为空,将进行依赖收集
    this.value = data[key]; // 触发属性的getter,完成依赖收集
    Dep.target = null;
  }
  update() {
    this.callback(this.value); // 数据变化时触发回调
  }
}

// `全局依赖映射表`(存储对象属性对应的Dep实例)
const targetMap = new WeakMap();

// 数据劫持:Proxy代理对象
function reactive(obj) {
  return new Proxy(obj, {
    get(target, key) {
      const dep = getDep(target, key);
      dep.addSub(Dep.target); // 收集依赖[[20]]
      return Reflect.get(target, key);
    },
    set(target, key, newVal) {
      const dep = getDep(target, key);
      const result = Reflect.set(target, key, newVal);
      dep.notify(); // 触发更新[[12]]
      return result;
    }
  });
}

// 获取属性对应的Dep实例
function getDep(target, key) {
	//1.每个对象对应一个map连接到全局依赖映射表
  let depsMap = targetMap.get(target);
  if (!depsMap) {
    depsMap = new Map();
    targetMap.set(target, depsMap);
  }
  //2.每个属性对应一个map连接到对象的映射表
  let dep = depsMap.get(key);
  if (!dep) {
    dep = new Dep();
    depsMap.set(key, dep);
  }
  return dep;
}

// 示例使用
const data = reactive({ count: 0 });

new Watcher(data, 'count', (newVal) => {
  console.log('Proxy视图更新:', newVal);
});

data.count = 2; // 输出:Proxy视图更新: 2



发布订阅

// 创建一个简单的发布订阅者管理类  
class EventEmitter {  
    constructor() {  
        this.events = {}; // 用于存储事件的字典,键为事件名,值为订阅者数组  
    }  
  
    // 订阅事件  
    on(eventName, callback) {  
        if (!this.events[eventName]) {  
            this.events[eventName] = []; // 如果该事件尚未被订阅,则初始化一个空数组  
        }  
        this.events[eventName].push(callback); // 将回调函数添加到订阅者数组中  
        return this; // 支持链式调用  
    }  
  
    // 取消订阅事件  
    off(eventName, callback) {  
        if (this.events[eventName]) {  
            // 移除指定的回调函数  
            this.events[eventName] = this.events[eventName].filter(cb => cb !== callback);  
            // 如果订阅者数组为空,则删除该事件  
            if (this.events[eventName].length === 0) {  
                delete this.events[eventName];  
            }  
        }  
        return this; // 支持链式调用  
    }  
  
    // 发布事件  
    emit(eventName, ...args) {  
        if (this.events[eventName]) {  
            // 遍历订阅者数组,并执行每个回调函数  
            this.events[eventName].forEach(callback => {  
                callback.apply(this, args);  
            });  
        }  
        return this; // 支持链式调用  
    }  
  
    // 可选:监听一次后自动取消订阅  
    once(eventName, callback) {  
        const onceCallback = (...args) => {  
            callback.apply(this, args);  
            this.off(eventName, onceCallback);  
        };  
        this.on(eventName, onceCallback);  
        return this; // 支持链式调用  
    }  
}  
  
// 使用示例  
const eventBus = new EventEmitter();  
  
// 订阅者1  
function subscriber1(price) {  
    console.log('订阅者1收到消息:当前价格已降至' + price + '元');  
}  
  
// 订阅者2  
function subscriber2(price) {  
    console.log('订阅者2也收到消息:价格更新为' + price + '元');  
}  
  
// 订阅事件  
eventBus.on('priceUpdate', subscriber1);  
eventBus.on('priceUpdate', subscriber2);  
  
// 使用once方法监听一次  
eventBus.once('specialOffer', (offer) => {  
    console.log('只接收一次的特别优惠:' + offer);  
});  
  
// 发布事件  
eventBus.emit('priceUpdate', 99); // 订阅者1和订阅者2都会收到消息  
eventBus.emit('specialOffer', '买一赠一'); // 只有一个订阅者会收到这个特别优惠的消息  
  
// 取消订阅  
eventBus.off('priceUpdate', subscriber1);  
eventBus.emit('priceUpdate', 88); // 只有订阅者2会收到消息

模板解译

在这里插入图片描述
在这里插入图片描述

Vue2&3 Diff

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

5.Redux、React-Router、Ant Design和Webpack等React⼯程化⼯具库
Redux

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

const fetchFoodsList = () => {  
  return async (dispatch) => {  
    // 编写异步逻辑  
    const res = await axios.get('http://localhost:3004/takeaway')  
    // 调用dispatch函数提交action  
    dispatch(setFoodsList(res.data))  
  }  
}
 
——————————————————————————————————————————————————————————————————————————————————
import React, { useEffect } from 'react';  
import { useDispatch, useSelector } from 'react-redux';  
import { fetchFoodsList } from './actions'; // 假设actions.js是你的action creators文件  
  
const FoodsComponent = () => {  
  const dispatch = useDispatch();  
  const foodsList = useSelector(state => state.foodsList); // 假设你的state结构中有foodsList  
  
  useEffect(() => {  
    dispatch(fetchFoodsList());  
  }, [dispatch]);  
  
  return (  
    <div>  
      {/* 渲染foodsList */}  
    </div>  
  );  
}
React-Router

React-router面试常考
在这里插入图片描述

Ant Design

在这里插入图片描述

Webpack

Webpack
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

devServer: {
    host: '0.0.0.0',
    port: port,
    open: false,
    proxy: {
      [process.env.VUE_APP_BASE_API]: {
        target: `http://localhost:8080`,
        changeOrigin: true,
        pathRewrite: {
          ['^' + process.env.VUE_APP_BASE_API]: ''
        }
      },
      // Tomcat上的资源+项目部署在Tomcat上则不存在跨域
      [process.env.VUE_APP_BASE_TOM]: {
        target: `http://localhost:8010`,
        changeOrigin: true,
        pathRewrite: {
          ['^' + process.env.VUE_APP_BASE_TOM]: ''
        }
      },
      [process.env.VUE_APP_BASE_PY]:{
        target: `http://localhost:5010`,
        changeOrigin: true,
        pathRewrite: {
          ['^' + process.env.VUE_APP_BASE_PY]: ''
        }
      }
    },
    disableHostCheck: true
  },

在这里插入图片描述
在这里插入图片描述

6.熟练使⽤Vuex、Pinia、Vue-Router、Element-UI和Vite等Vue⼯程化⼯具库
Vue2&Vue3&React

在这里插入图片描述
生命周期
在这里插入图片描述
在这里插入图片描述
React钩子

Vuex&Pinia

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Vue-Router

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Element-UI

Vue中动态样式绑定+CSS变量实现切换明暗主题功能——从入门到进阶

Vue3+Element Plus项目国际化_vue-i18n

<template>
  <div>
    <h1>{{ $t('message.hello') }}</h1>
    <p>{{ $t('message.welcome') }}</p>
    <el-button @click="toggleLanguage">切换语言</el-button>  <!-- Element Plus 按钮 -->
  </div>
</template>

<script>
import { useI18n } from 'vue-i18n'

export default {
  setup() {
    const { t, locale } = useI18n()

    const toggleLanguage = () => {
      const newLang = locale.value === 'zh' ? 'en' : 'zh'
      locale.value = newLang  // 切换语言
    }

    return {
      t,
      toggleLanguage
    }
  }
}
</script>

<style scoped>
/* 样式可以根据需要进行调整 */
</style>

在这里插入图片描述
在这里插入图片描述

Vite

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

7.掌握单例、⼯⼚、观察者、发布订阅、代理和装饰器等设计模式

以下是基于 JavaScript 实现的常见设计模式的代码示例和简要分析,包括 单例模式工厂模式观察者模式发布订阅模式代理模式装饰器模式


1. 单例模式 (Singleton Pattern)

代码实现

class Singleton {
  constructor() {
    if (Singleton.instance) {
      return Singleton.instance; // 如果实例已存在,直接返回
    }
    this.name = "Singleton Instance";
    Singleton.instance = this; // 保存实例
  }

  getName() {
    return this.name;
  }
}

// 测试
const instance1 = new Singleton();
const instance2 = new Singleton();

console.log(instance1 === instance2); // true
console.log(instance1.getName()); // Singleton Instance

分析
核心思想:确保一个类只有一个实例,并提供全局访问点。
应用场景:数据库连接池、日志记录器、配置管理器等需要全局唯一的场景。


2. 工厂模式 (Factory Pattern)

代码实现

class Car {
  constructor(type) {
    this.type = type;
  }

  drive() {
    console.log(`${this.type} car is driving.`);
  }
}

class CarFactory {
  createCar(type) {
    return new Car(type);
  }
}

// 测试
const factory = new CarFactory();
const car1 = factory.createCar("Sedan");
const car2 = factory.createCar("SUV");

car1.drive(); // Sedan car is driving.
car2.drive(); // SUV car is driving.

分析
核心思想:通过工厂类封装对象的创建逻辑,客户端无需关心具体的创建过程。
应用场景:需要根据条件动态创建对象的场景,比如创建不同类型的 UI 组件。


3. 观察者模式 (Observer Pattern)

代码实现

class Subject {
  constructor() {
    this.observers = [];
  }

  addObserver(observer) {
    this.observers.push(observer);
  }

  removeObserver(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 data: ${data}`);
  }
}

// 测试
const subject = new Subject();
const observer1 = new Observer("Observer1");
const observer2 = new Observer("Observer2");

subject.addObserver(observer1);
subject.addObserver(observer2);

subject.notify("Hello Observers!");
// Observer1 received data: Hello Observers!
// Observer2 received data: Hello Observers!

分析
核心思想:主题(Subject)维护一组观察者(Observer),当主题状态发生变化时,通知所有观察者。
应用场景:事件监听器、数据绑定(如 Vue 的响应式系统)。


4. 发布订阅模式 (Pub/Sub Pattern)

代码实现

class EventBus {
  constructor() {
    this.events = {};
  }

  subscribe(event, callback) {
    if (!this.events[event]) {
      this.events[event] = [];
    }
    this.events[event].push(callback);
  }

  unsubscribe(event, callback) {
    this.events[event] = this.events[event].filter(cb => cb !== callback);
  }

  publish(event, data) {
    if (this.events[event]) {
      this.events[event].forEach(callback => callback(data));
    }
  }
}

// 测试
const eventBus = new EventBus();

const callback1 = data => console.log(`Callback1: ${data}`);
const callback2 = data => console.log(`Callback2: ${data}`);

eventBus.subscribe("message", callback1);
eventBus.subscribe("message", callback2);

eventBus.publish("message", "Hello Pub/Sub!"); 
// Callback1: Hello Pub/Sub!
// Callback2: Hello Pub/Sub!

eventBus.unsubscribe("message", callback1);

eventBus.publish("message", "Hello again!"); 
// Callback2: Hello again!

分析
核心思想:发布者和订阅者通过事件总线(Event Bus)解耦,发布者只负责发布消息,订阅者只负责接收消息。
应用场景:消息队列、事件驱动架构。


5. 代理模式 (Proxy Pattern)

代码实现

class RealSubject {
  request() {
    console.log("RealSubject: Handling request.");
  }
}

class Proxy {
  constructor(realSubject) {
    this.realSubject = realSubject;
  }

  request() {
    console.log("Proxy: Preprocessing request.");
    this.realSubject.request();
    console.log("Proxy: Postprocessing request.");
  }
}

// 测试
const realSubject = new RealSubject();
const proxy = new Proxy(realSubject);

proxy.request();
// Proxy: Preprocessing request.
// RealSubject: Handling request.
// Proxy: Postprocessing request.

分析
核心思想:代理类控制对真实对象的访问,可以在访问前后添加额外的逻辑。
应用场景:权限控制、懒加载、日志记录。


6. 装饰器模式 (Decorator Pattern)

代码实现

class Coffee {
  cost() {
    return 5; // 基础咖啡价格
  }
}

class MilkDecorator {
  constructor(coffee) {
    this.coffee = coffee;
  }

  cost() {
    return this.coffee.cost() + 2; // 加牛奶的价格
  }
}

class SugarDecorator {
  constructor(coffee) {
    this.coffee = coffee;
  }

  cost() {
    return this.coffee.cost() + 1; // 加糖的价格
  }
}

// 测试
let coffee = new Coffee();
console.log("Basic Coffee:", coffee.cost()); // 5

coffee = new MilkDecorator(coffee);
console.log("Milk Coffee:", coffee.cost()); // 7

coffee = new SugarDecorator(coffee);
console.log("Milk and Sugar Coffee:", coffee.cost()); // 8

分析
核心思想:通过装饰器动态扩展对象的功能,而不改变其原始结构。
应用场景:功能扩展、插件系统。


7.总结对比
设计模式核心思想应用场景
单例模式确保一个类只有一个实例,并提供全局访问点。数据库连接池、日志记录器、配置管理器。
工厂模式封装对象的创建逻辑,客户端无需关心具体的创建过程。动态创建不同类型的 UI 组件。
观察者模式主题维护一组观察者,状态变化时通知所有观察者。事件监听器、数据绑定。
发布订阅模式发布者和订阅者通过事件总线解耦,发布者只负责发布消息,订阅者只负责接收消息。消息队列、事件驱动架构。
代理模式代理类控制对真实对象的访问,可以在访问前后添加额外的逻辑。权限控制、懒加载、日志记录。
装饰器模式动态扩展对象的功能,而不改变其原始结构。功能扩展、插件系统。

8.熟悉并掌握WebGL技术,掌握渲染管线、着⾊器编程和主流开源三维引擎

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

9. 熟悉使⽤Express开发RSETful API,通过分层架构解耦业务逻辑,增强系统可拓展性

在这里插入图片描述
在这里插入图片描述

10 掌握使⽤Git进⾏协作开发、Apifox进⾏测试,以及Ngnix、Tomcat进⾏部署
Git

在这里插入图片描述

Nginx

在这里插入图片描述

测试&CI/CD

一文弄懂前端CI/CD——原理、流程以及相关内容详解
在这里插入图片描述

11.计算机网络与浏览器

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

相关文章:

  • JVM的一些知识
  • 如何在项目中有效管理设计模式的复杂性
  • 达梦数据库主备切换技术解析与实践指南
  • 《数字图像处理》第三章3.3直方图处理学习笔记
  • Java面试第十一山!《SpringCloud框架》
  • ArcGIS10. 8简介与安装,附下载地址
  • nginx 日志切割
  • Docker进阶篇1:什么是Docker数据卷?为什么需要Docker数据卷?Docker数据卷3种类型介绍
  • 5、MySQL为什么使用 B+树 来作索引【高频】
  • 【机器学习chp14 — 2】生成式模型—变分自编码器VAE(超详细分析,易于理解,推导严谨,一文就够了)
  • 从零开始实现 C++ TinyWebServer 缓冲区 Buffer类详解
  • 【万字总结】前端全方位性能优化指南(一)——Brotli压缩、CDN智能分发、资源合并
  • 界面控件DevExpress WinForms v25.1预览 - 提升.NET开发效率
  • Spark 中agg的用法
  • 《Python深度学习》第四讲:计算机视觉中的深度学习
  • AI实干家:HK深度体验-【第3篇-香港、新加坡、深圳、上海、首尔五座城市在金融数据维度的对比分析】
  • 【机器学习chp14 — 1】生成式模型概述和主要思想(超详细分析,易于理解,推导严谨,一文就够了)
  • ArkTS 基础语法介绍
  • Oracle Exadata KVM 虚拟化
  • Kafka 八股文
  • 文化体验+商业消费+服务创新,上海搭建入境旅游新模式
  • 谢震业、梁小静等名将在列,世界田联接力赛中国队名单出炉
  • 三大猪企去年净利润同比均较大幅度增长,资产负债率齐降
  • 企业称县政府为拆迁开发借款2亿元逾期未还,河北青龙县:开发搁置,将继续沟通
  • 《哪吒之魔童降世》电影版权方诉《仙侠神域》游戏运营方侵权案开庭
  • 商务部:美方应彻底取消所有对华单边关税措施