【前端面经】整理0528

267 阅读8分钟

基础

JS

HTML & CSS

【前端面经】HTML&CSS

移动端

  1. 移动端如何做兼容、性能优化?

移动端做兼容,主要考虑以下几方面:

  • 了解不同设备和浏览器(Safari、Chrome等)以及发布版本的功能兼容,识别并测试;
  • 适配不同分辨率和屏幕尺寸:使用响应式布局和弹性盒模型等技术、媒体查询配置等;
  • 处理移动端特有事件和API:触摸事件等、利用检测库来判断设备是否支持特定API或者功能等;
  • 考虑不同操作系统的兼容性:使用框架提供的组件和API,简化跨平台开发的复杂性;
  • 测试和修复兼容性问题:通过模拟器、真机模拟等方式;

性能优化:

  • 减少网络请求:合并、压缩文件、使用缓存策略等,减少请求次数、减少重复请求;
  • 优化UI渲染:减少DOM操作次数、优化图片加载和使用,使用合适的图片格式、压缩图片、懒加载等技术;
  • 使用缓存:缓存一切可缓存资源,使用长Cache策略,通过时间戳等方式更新缓存资源;
  • 压缩HTML、CSS、JS等文件;
  • 优化首屏加载:按需加载;
  • 性能监测和优化:使用性能分析工具(如Chrome开发者工具、Safari Web Inspector等)监测应用的性能瓶颈;合理管理和释放资源,避免内存泄漏和性能下降;
  • 更新和维护:定期进行性能评估和优化,及时更新和保持设备应用兼容性和用户体验。

Vue部分

Vue是如何收集依赖的

Vue依赖收集发生在defineReactive()方法中,在方法内new Dep()实例化一个Dep()实例,然后在getter中通过dep.depend()方法对数据依赖进行收集,然后在setter中通过dep.notify()通知更新。整个Dep其实就是一个观察者,把收集的依赖存储起来,在需要的时候进行调用。在收集数据依赖的时候,会为数据创建一个Watcher,当数据发生改变通知每个Watcher,由它来进行更新渲染。

webpack

react部分

  1. vue和react的相同点和不同点
  2. react keep-alive是怎么做的?
  3. react生产问题怎么定位到具体错误代码行数?
  4. vue和react源码用了哪些设计模式
  5. react页面白屏检测

网络

【前端面经】网络篇

环境配置

  1. 用nginx处理过什么问题,高并发怎么解决,如何控制用户的访问量?
  2. nginx使用场景是什么?反向代理如何使用?图片防盗链如何做?
  3. docker如何配置CI、CD?
  4. 如何用jenkins完整跑一个CI、CD(搭建项目至投入生产)?
  5. cdn用的那个厂商的,怎么配置缓存策略
  6. 性能埋点,有哪些点需要获取?
    • JavaScript 错误:捕获 JavaScript 运行时错误,例如语法错误、引用错误等。
    • 网络错误:捕获网络请求失败的情况,例如 HTTP 状态码 404、500 等。
    • 用户交互异常:捕获用户与页面交互时的异常情况,例如表单提交失败、按钮点击无响应等。
    • 浏览器兼容性问题:捕获不同浏览器版本或设备上可能出现的兼容性问题。
    • 资源加载异常:捕获图片、字体、样式表等资源加载失败的情况。

实操题

  1. 后端200M数据渲染在页面卡顿如何解决?一屏展示不下呢?
  • 通过requestAnimationFrame+fragment时间分片;

requestAnimationFrame也是个定时器,时间取决于当前电脑的刷新率,60HZ则16.7ms执行一次;document.createDocumentFragment()创建时间分片,最后回流挂载在ul上。

  • 虚拟列表:获取所有数据,获取可视区高度,计算数据分片展示;
 // 可视区放下多少个li
const itemNum = computed(() => {
    return ~~(boxHeight.value / itemHeight.value) + 2
})

const startIndex = ref(0) // 索引

// 页面滚动
const doScroll = () => { // div内部滚动距离 / 每项的高度 = 滚了多少项
    const index = ~~(scrollBox.value.scrollTop / itemHeight.value)
    if (index === startIndex.value) return // 滚到最开始的位置
    startIndex.value = index // 可视区的第一条数据下标
}


const endIndex = computed(() => { // 可视区最后一个下标
    let index = startIndex.value + itemNum.value * 2 // 考虑用户体验,准备可视区一倍的li
    if (!allList.value[index]) { // 已经滚超了,回来一个位置
        index = allList.value.length - 1
    } 
    return index
})

const currentList = computed(() => {
    let index = 0
    if (startIndex.value <= itemNum.value) { // [0, 21] [0, 22] …… [0, 30] [1, 31]
        index = 0
    } else {
        index = startIndex.value - itemNum.value
    }
    return allList.value.slice(index, endIndex.value + 1)
})

// 根据当前可见区域前后的空白区域高度,动态计算样式,确保滚动的平滑性
const blankStyle = computed(() => {
    let index = 0;
    if (startIndex.value <= itemNum.value) {
        index = 0;
    } else {
        index = startIndex.value - itemNum.value;
    }
    return {
        paddingTop: index * itemHiehgt.value + "px",

        paddingBottom: (allList.value.length - endIndex.value - 1) * itemHiehgt.value + "px"           
    };
});


  1. 怎么做的主应用或子应用单独启动
  2. 子应用单独启动情况下怎么获取主应用的cookie信息
  3. 业务的页面卡顿怎么解决
  4. 实际业务大数据量DOM渲染优化
  5. 自研自动化打包部署脚本
  6. 如何实现大文件上传

Blob 上自带一个 slice 方法:Blob.slice(起始字节, 最终字节),返回Blob对象。将切片文件数组数据转换为表单格式传给后端,通过Promise.all并发发给后端,传输完毕后发送一个合并请求,带上文件名和切片大小信息。

问题:
- 耗时长;
- nginx反向代理映射时间超时;
- 无法得知上传进度,无法暂停;

解决办法:分片上传

// 切片数量需要和后端协商具体最大切片数做计算
const createChunk = (file, size = 2 * 1024 * 1024) => {
    const chunkList = [] // 切片
    let cur = 0  // 切的进度
    // 循环切
    while (cur < file.size) {
        chunkList.push({ file: file.slice(cur, cur + size) })
        cur += size
    }
    return chunkList
}

// 上传切片
const uploadChunks = () => {
    const formateList = uploadChunkList.value.map(({ file, fileName, index, chunkName }) => {
        // 对象需要转成二进制数据流进行传输
        const formData = new FormData() // 创建表单格式的数据流
        // 将切片转换成了表单的数据流
        formData.append('file', file)
        formData.append('fileName', fileName)
        formData.append('chunkName', chunkName)
        return { formData, index }
    })
    
    const requestList = formateList.map(({ formData, index }) => {
        // axios[method](url, data, { headers, onUploadProgress })
        return requestUpload({
            url: 'http://localhost:3000/upload',
            data: formData,
            onUploadProgress: createProgress(uploadChunkList.value[index]) // 进度条函数拿出来写
        })
    })
    // 合并切片请求
    Promise.all(requestList).then(mergeChunks())
}


其它

  • 万一某一切片上传失败,怎么处理?—— 捕获索引,提示,或者重新上传;
  • 一旦断网就要重新上传,如何解决?—— 断点续传
  1. http2.0特性,头部压缩怎么实现的
  2. csrf从前后端角度实现预防,你说的是常规的方案,要实现完全预防怎么做
  3. 项目是否用到typescript
  4. 项目是否用到自动化测试
  5. 302怎么确定重定向路径
  6. promise(A).catch(f1).then(f2),f1执行后f2回执行吗,为什么
  7. new String('123')String('123')有什么区别?new String('123')==String('123')吗,typeof判断这两个是什么?

手写题

  1. 手写Promise.all
  2. 正则路径匹配
const reg = /\.js$/; // 匹配js文件:以.js结尾
console.log(reg.test('/sd/abc.js')); // 输出true

// `(\d+)`是一个捕获组,它匹配一个或多个数字,并将匹配的结果保存在结果数组的索引1中(索引0是整个匹配的结果)
const regURL = /^\/users\/(\d+)\/profile$/;
console.log(regURL.test('/users/23/profile')); // 输出true
const res = regURL.exec('/users/123/profile')
console.log('ID: ' + res[1]); // 输出:ID: 123
  1. 解析URL的query信息,转换为对象形式
const url = 'https://www.baidu.com/abc?a=1&b=2&c#hash';
Object.fromEntries((new URL(url)).searchParams.entries());
  1. 手写对象扁平化
  2. 手写eventloop时序考察
  3. 手写全排列
  4. 手写防抖
  5. 手写快排
  6. 实现字符串前缀匹配
  7. 版本号比较
  8. 正则写13-15位大写字母或数字
  9. 三个页面地址为www.baidu.com/a,www.baidu.com/b,www.qq.com, sessionStorage是否能在这些页面共享,为什么 localstorage呢
  10. 有效括号匹配
  11. 判断b是否是a的子集(a和b有重复元素,要求b的同个元素出现次数<=a的同个元素出现次数)
  12. js对象数组转树形结构
  13. 将某一串数字,转为财务格式,千分位加逗号。例如:2345.6 =》2,345.6
const reg = /\B(?=(\d{3})+(?!\d))/g
const num = 2345.6
console.log(num.replace(reg, ','))

其它

  1. 登录鉴权是如何做的

  2. Linux命令考察

  3. docker是怎么实现选取镜像并启动容器

  4. cicd的理解和具体实现

  5. 实现一个单据功能的接口数据传输格式,从后端角度考虑为什么要这么传

  6. 如果重构系统,你会怎么做?

  7. 大数据业务理解?埋点怎么做的?

  8. 多窗口通信怎么做?

  9. proxySandbox和legacySandbox那个更好,为什么

  10. legacySandbox会存在变量污染吗

  11. legacysanbox是完全隔离吗,怎么实现完全隔离,在IE浏览器下怎么实现

  12. setState是同步还是异步,为什么?

  13. 树摇原理,编译阶段怎么确定代码是否引用,怎么确定要不要删除的

  14. input怎么确定scheme结构?

  15. scheme是什么?

  16. webassembly了解过吗

  17. 数据大屏如何做响应式?

  18. 算法会哪些?

  19. 时间复杂度和空间复杂度怎么理解

  20. redis nginx场景题

  21. nginx try_files具体怎么使用

  22. redis和k8s使用场景举例