文章列表
记录前端学习与面试的点滴
字节跳动前端面试心得
今天参加了字节跳动的一面,面试岗位是前端开发实习生。本次算是一次试水,看看自己掌握的技能和那些大厂要求的差距,补足一下自己的短板。记录了面试流程、代码题以及反思总结。
深入理解 Promise 与异步编程
从回调地狱到 Promise 链式调用,再到 async/await 语法糖,梳理 JavaScript 异步编程的演进脉络与核心原理。
响应式布局实战:从媒体查询到容器查询
梳理响应式布局的核心技术方案,包括 rem、vw/vh、媒体查询、flex 与 grid 布局,以及新一代容器查询的应用场景。
Vue3 组合式 API 最佳实践
分享在使用 Vue3 Composition API 开发中的一些心得体会,包括响应式数据设计、组合函数抽取与类型推导优化。
字节跳动前端面试心得
今天参加了字节跳动的一面,面试岗位是前端开发实习生。主要是在飞书的线上面试,虽然出现了耳机没带、电脑检测不到摄像头、网络卡等问题,不过其他都挺顺利的。
本次也算是一次试水,看看自己掌握的技能和那些大厂要求的差距,补足一下自己的短板,下面打算记录一下本次面试。
面试流程
自我介绍
中规中矩,简单介绍了一下我为什么选择前端开发,是因为出于兴趣和爱好。
聊了聊我的学习历程,在大学学习了 Vue(不小心说成"系统性的学习了 Vue",为后面拷打 Vue 的底层原理埋下了伏笔)。
还在此期间学了前后端的相关知识,另外做了一些项目,包括自己做的和老师做的。
介绍一下自己的项目经历
简单介绍了下自己的个人开发的网站,接着拿了一个 Uniapp 的项目举例,介绍了一下自己如何做技术选型,如何开发,如何部署。
小程序开发和网页开发有什么不一样
我主要回答了两点:
- 响应式布局
- 性能差异
围绕响应式布局问了一些 CSS 的问题:
font-size 的比例来计算,通常设置 html { font-size: 62.5%; } 使得 1rem = 10px,方便换算。
围绕性能差异又问了些:
接着问了些 Vue 相关的问题:
问一些前后端的问题
Access-Control-Allow-Origin 头部并不够,还需要处理 Access-Control-Allow-Methods、Access-Control-Allow-Headers 等。
代码题
1. 数组转嵌套对象
将 ['a', 'b', 'c', 'd'] 转换成嵌套对象:{a: {b: {c: 'd'}}}。
当时写了半天没写出来(数组方面都没怎么准备),说了下大致思路:做一个嵌套函数,每一层数组取最后两位转为对象。
// 输入:['a','b','c','d'] 输出:{a: {b: {c: 'd'}}}
function buildObject(arr) {
return arr.reverse().reduce((acc, cur) => ({ [cur]: acc }))
}
2. 写一个倒计时组件(Vue)
要求:显示 60 秒,有暂停按钮,有重置按钮。
用 setInterval 写了一个倒计时组件。之后追问:
基础代码实现:
<script setup>
import { ref } from 'vue'
const totalTime = 60 // 秒
const timeLeft = ref(totalTime)
let timer = null
const start = () => {
if (timer) return
timer = setInterval(() => {
timeLeft.value--
if (timeLeft.value <= 0) {
clearInterval(timer)
timer = null
}
}, 1000)
}
const pause = () => {
clearInterval(timer)
timer = null
}
const reset = () => {
clearInterval(timer)
timer = null
timeLeft.value = totalTime
}
</script>
<template>
<div>
<h2>{{ timeLeft }} 秒</h2>
<button @click="start">开始</button>
<button @click="pause">暂停</button>
<button @click="reset">重置</button>
</div>
</template>
显示毫秒的格式化函数:
function formatTime(ms) {
const sec = Math.floor(ms / 1000)
const ms2 = Math.floor((ms % 1000) / 10).toString().padStart(2, '0')
return `${sec}.${ms2}`
}
使用时间戳差值优化版本:
<script setup>
import { ref } from 'vue'
const total = 60000 // ms
const timeLeft = ref(total)
let timer = null
let startTime = 0
let pauseOffset = 0
const format = (ms) => {
const sec = Math.floor(ms / 1000)
const ms2 = Math.floor((ms % 1000) / 10).toString().padStart(2, '0')
return `${sec}.${ms2}`
}
const tick = () => {
const elapsed = Date.now() - startTime
timeLeft.value = Math.max(total - elapsed - pauseOffset, 0)
if (timeLeft.value <= 0) {
clearInterval(timer)
timer = null
}
}
const start = () => {
if (timer) return
startTime = Date.now() - (total - timeLeft.value)
timer = setInterval(tick, 16) // 60fps
}
const pause = () => {
clearInterval(timer)
timer = null
pauseOffset += Date.now() - startTime
}
const reset = () => {
clearInterval(timer)
timer = null
timeLeft.value = total
pauseOffset = 0
}
</script>
<template>
<div>
<h2>{{ format(timeLeft) }} 秒</h2>
<button @click="start">开始</button>
<button @click="pause">暂停</button>
<button @click="reset">重置</button>
</div>
</template>
反思
知识盲区
| 知识点 | 暴露问题 |
|---|---|
| Vue 响应式原理 | 仅知 Proxy,不清楚 defineProperty 的底层 |
| Vue 编译流程 | 完全不了解模板编译流程 |
| CSS 响应式布局 | 了解 rem、rpx 用法,但不能解释细节 |
| 跨域 CORS | 能答出头部字段,但不知道"加一个响应头并不够" |
暴露出的问题
- 基础知识不够系统、容易被"连环追问压垮"
- 项目成果略模糊,缺乏"结果导向表达"
- 临场描述卡顿,表达略缺乏术语与层次
下一次准备
- Vue 源码概览
- CSS 响应式布局语法梳理(rem / rpx / media query / flex / grid)
- 跨域 CORS 原理总结(理解预检请求、浏览器限制对象)
- 准备 Vue 常见高频问题(响应式、生命周期、组件通信、diff 算法、双向绑定)
- reduce 类结构题多练(嵌套构造、对象映射)
- 组件类题目(计时器、列表渲染、滑动窗口、表单绑定、节流防抖)
-- 全文完 --