前端基础面试题及答案
一、HTML
1. HTML5 新增了哪些特性?
- 语义化标签:
<header><footer><nav><section><article><aside> - 新表单类型:
emailnumberdaterangesearch等 - 多媒体标签:
<audio><video> - Canvas / SVG 绘图
- 本地存储:
localStoragesessionStorage - WebSocket、地理定位、拖拽 API
2. src 和 href 的区别?
src:引入资源并替换当前元素(如<img><script>),会暂停页面解析href:建立文档与资源的关联(如<a><link>),不会暂停解析
3. 行内元素和块级元素的区别?
| 块级元素 | 行内元素 | |
|---|---|---|
| 是否独占一行 | 是 | 否 |
| 宽高设置 | 可以 | 不可以 |
| 常见标签 | div、p、h1-h6 | span、a、img |
二、CSS
4. CSS 盒模型是什么?
- 标准盒模型(
box-sizing: content-box):width只包含内容区,实际宽度 = width + padding + border - 怪异盒模型 / IE 盒模型(
box-sizing: border-box):width包含内容 + padding + border,实际宽度 = width
怪异盒模型因早期 IE 浏览器的非标准实现而得名,现在通过
box-sizing: border-box主动使用,实际开发中反而更常用,因为更直观好控制尺寸。
5. BFC 是什么,如何触发?
BFC(块级格式化上下文)是一个独立的渲染区域,内部元素不影响外部。
触发条件:
overflow不为visibledisplay: flex / inline-block / tableposition: absolute / fixedfloat不为none
作用:清除浮动、防止 margin 重叠
6. 垂直居中的几种方式?
css
/* 方式一:flex */
.parent {
display: flex;
align-items: center;
justify-content: center;
}
/* 方式二:absolute + transform */
.child {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
/* 方式三:absolute + margin auto */
.child {
position: absolute;
top: 0; bottom: 0; left: 0; right: 0;
margin: auto;
width: 100px;
height: 100px;
}
7. CSS 选择器优先级?
从高到低:!important > 行内样式 > ID > 类/伪类/属性 > 标签 > *
用数字表示:0, 1, 0, 0 (ID) > 0, 0, 1, 0 (class) > 0, 0, 0, 1 (tag)
8. flex 布局常用属性?
css
/* 容器属性 */
display: flex;
flex-direction: row | column; /* 主轴方向 */
justify-content: center | space-between; /* 主轴对齐 */
align-items: center | flex-start; /* 交叉轴对齐 */
flex-wrap: wrap; /* 是否换行 */
/* 子项属性 */
flex: 1; /* flex-grow: 1, flex-shrink: 1, flex-basis: 0 */
align-self: ...; /* 单独设置交叉轴对齐 */
order: 1; /* 排列顺序 */
三、JavaScript
9. var / let / const 的区别?
| var | let | const | |
|---|---|---|---|
| 作用域 | 函数作用域 | 块级作用域 | 块级作用域 |
| 变量提升 | 有(值为 undefined) | 有(暂时性死区) | 有(暂时性死区) |
| 重复声明 | 允许 | 不允许 | 不允许 |
| 可重新赋值 | 是 | 是 | 否 |
10. 什么是闭包?
函数内部可以访问外部函数变量,即使外部函数已执行完毕。
javascript
function counter() {
let count = 0;
return function() {
return ++count;
};
}
const add = counter();
add(); // 1
add(); // 2
应用场景:防抖节流、模块化、数据私有化
11. == 和 === 的区别?
===:严格相等,类型和值都要相同==:宽松相等,会进行类型转换
常见陷阱:
javascript
0 == false // true
'' == false // true
null == undefined // true
null === undefined // false
12. 事件循环(Event Loop)?
JavaScript 是单线程的,通过事件循环处理异步:
- 执行同步代码(调用栈)
- 执行所有微任务(Promise.then、MutationObserver)
- 执行一个宏任务(setTimeout、setInterval、I/O)
- 重复 2-3
javascript
console.log(1);
setTimeout(() => console.log(2), 0);
Promise.resolve().then(() => console.log(3));
console.log(4);
// 输出:1 4 3 2
13. 深拷贝和浅拷贝?
- 浅拷贝:只拷贝第一层,引用类型仍共享内存(
Object.assign、扩展运算符) - 深拷贝:完整复制所有层级
javascript
// 简单深拷贝(不能处理函数、循环引用)
const deep = JSON.parse(JSON.stringify(obj));
// 手写深拷贝
function deepClone(obj) {
if (obj === null || typeof obj !== 'object') return obj;
if (Array.isArray(obj)) return obj.map(deepClone);
return Object.fromEntries(
Object.entries(obj).map(([k, v]) => [k, deepClone(v)])
);
}
14. 防抖和节流?
防抖(debounce):一段时间内只执行最后一次(搜索框输入)
javascript
function debounce(fn, delay) {
let timer = null;
return function(...args) {
clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, args), delay);
};
}
节流(throttle):一段时间内只执行第一次(滚动事件)
javascript
function throttle(fn, interval) {
let last = 0;
return function(...args) {
const now = Date.now();
if (now - last >= interval) {
last = now;
fn.apply(this, args);
}
};
}
15. Promise 的三种状态?
pending:初始状态fulfilled:成功rejected:失败
状态只能从 pending → fulfilled 或 pending → rejected,不可逆。
javascript
const p = new Promise((resolve, reject) => {
// 异步操作
resolve('success'); // 或 reject('error')
});
p.then(res => console.log(res))
.catch(err => console.log(err))
.finally(() => console.log('done'));
四、浏览器/网络
16. 从输入 URL 到页面展示经历了什么?
- DNS 解析域名 → IP 地址
- 建立 TCP 连接(三次握手)
- 发送 HTTP 请求
- 服务器返回响应
- 浏览器解析 HTML,构建 DOM 树
- 解析 CSS,构建 CSSOM 树
- 合并为 Render Tree
- 布局(Layout)→ 绘制(Paint)→ 合成(Composite)
17. HTTP 缓存机制?
强缓存(不请求服务器):
Cache-Control: max-age=3600Expires: 过期时间
协商缓存(询问服务器是否更新):
Last-Modified/If-Modified-SinceETag/If-None-Match(更精准,优先使用)- 未修改返回 304,修改返回 200 + 新资源
18. 跨域是什么,如何解决?
同源策略:协议 + 域名 + 端口 完全相同才算同源。
解决方案:
- CORS :服务端设置
Access-Control-Allow-Origin(最常用) - 代理:开发环境 webpack devServer proxy 转发
- JSONP:只支持 GET,利用 script 标签不受同源限制
- postMessage:跨 iframe 通信
19. localStorage / sessionStorage / Cookie 区别?
| Cookie | localStorage | sessionStorage | |
|---|---|---|---|
| 大小 | 4KB | 5MB | 5MB |
| 过期时间 | 可设置 | 永久 | 关闭标签页清除 |
| 随请求发送 | 是 | 否 | 否 |
| 作用域 | 可跨标签页 | 同源共享 | 当前标签页 |
20. XSS 和 CSRF 攻击?
XSS(跨站脚本攻击):注入恶意脚本
- 防御:对输入输出转义、Content-Security-Policy
CSRF(跨站请求伪造):伪造用户请求
- 防御:Token 验证、检查 Referer、SameSite Cookie
五、Vue 基础
21. v-if 和 v-show 区别?
v-if:条件为假时不渲染 DOM,适合切换不频繁的场景v-show:始终渲染,用display:none控制显隐,适合频繁切换
22. computed 和 watch 区别?
| computed | watch | |
|---|---|---|
| 有无返回值 | 有 | 无 |
| 是否缓存 | 是(依赖不变不重新计算) | 否 |
| 适用场景 | 依赖数据计算出新值 | 监听数据变化执行副作用 |
23. Vue 生命周期?
beforeCreate → created → beforeMount → mounted → beforeUpdate → updated → beforeDestroy → destroyed
- 请求数据:
created或mounted - DOM 操作:
mounted - 清理定时器:
beforeDestroy
24. Vue2 响应式原理?
使用 Object.defineProperty 劫持对象属性的 getter/setter:
- getter 时收集依赖(Watcher)
- setter 时通知依赖更新
局限:无法检测数组下标修改、对象新增/删除属性(需用 $set)
Vue3 改用 Proxy,解决了上述问题。
25. Vue 组件通信方式?
- 父 → 子:
props - 子 → 父:
$emit - 跨层级:
provide/inject - 兄弟组件:EventBus 或 Vuex/Pinia
- 全局状态:Vuex / Pinia
共 25 题,涵盖 HTML / CSS / JavaScript / 浏览器网络 / Vue 基础