面试记录

57 阅读2分钟
# 字节跳动一面面试记录

**日期**: 2025年3月5日  
**时间**: 15:00

---

## 自我介绍

首先,面试官要求我进行自我介绍。我简要介绍了自己的教育背景、工作经历以及技术栈。

---

## 项目经验

### 项目日常迭代

面试官询问了我项目的日常迭代流程。我详细描述了项目从需求分析、设计、开发、测试到上线的完整流程,并强调了团队协作和代码审查的重要性。

---

## 技术难题

### 遇到的最困难的技术问题

我分享了一个在工作中遇到的技术难题,并详细说明了问题的背景、解决思路以及最终的解决方案。

---

## 前端开发

### 受控组件和非受控组件

- **受控组件**: 组件的状态由React或Vue管理,通过`props`和`state`来控制组件的行为和显示。
- **非受控组件**: 组件的状态由DOM自身管理,通常通过`ref`来获取DOM元素的值。

### 单页应用(SPA)和多页应用(MPA)的区别

- **单页应用**: 整个应用只有一个HTML页面,通过JavaScript动态加载内容。适用于需要快速响应用户交互的场景,如社交媒体平台。
- **多页应用**: 每个页面都是一个独立的HTML文件,适用于内容较多且需要SEO优化的场景,如新闻网站。

---

## 浏览器存储

### 浏览器存储方式及其差异

- **Cookie**: 存储容量小,每次请求都会携带,适合存储小量数据。
- **localStorage**: 存储容量较大,数据持久化,适合存储大量数据。
- **sessionStorage**: 存储容量较大,数据仅在当前会话有效,适合临时存储。

### 设置localStorage的最长保留时间

可以通过在存储数据时记录当前时间,并在读取数据时检查时间是否过期来实现。

### 用户长时间不用的解决方案

可以设置一个定时器,定期检查并清理过期的数据。

### 浏览器时间不可信的解决方案

可以使用后端接口来获取服务器时间,确保时间的准确性。

### 优化存储与读取的异步问题

可以考虑使用Web Worker来异步处理存储和读取操作,减少对主线程的阻塞。

---

## 代码题目

### 实现一个EventEmitter

```javascript
class EventEmitter {
  constructor() {
    this.events = {};
  }

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

  emit(event, ...args) {
    if (this.events[event]) {
      this.events[event].forEach(listener => listener(...args));
    }
  }

  removeListener(event, listener) {
    if (this.events[event]) {
      this.events[event] = this.events[event].filter(l => l !== listener);
    }
  }
}