📖 关于初级前端面试题
前端开发岗位面试是每位前端开发者职业生涯中必须面对的重要环节。无论是应届毕业生还是有一定工作经验的开发者,充分准备初级前端面试题都是获得理想offer的关键。本文将从多个维度系统梳理前端面试的核心知识点,帮助你全面备考。
🎯 面试考察的核心能力
企业在招聘初级前端开发岗位时,主要考察以下几个维度的能力:
- 基础扎实程度:HTML、CSS、JavaScript基础是否牢固,能否准确回答基础概念题
- 代码能力:是否具备基本的编码能力,能否手写常见算法和工具函数
- 框架理解:对主流前端框架(Vue/React)的理解深度和使用经验
- 工程化能力:是否了解构建工具、版本控制、代码规范等工程化知识
- 问题解决能力:面对实际开发问题时,能否快速定位并解决问题
- 学习能力:前端技术迭代迅速,持续学习的能力至关重要
📑 面试知识体系导航
点击左侧导航或下方标签,快速跳转到对应知识模块
📄 HTML面试题
HTML是前端开发的基础,以下是初级前端面试中HTML相关的高频考点
① HTML语义化标签有哪些?为什么使用语义化标签?
HTML语义化标签是指那些能够清晰表达其含义的标签,而非单纯的视觉呈现标签。常见的语义化标签包括:
<header>— 页面或区块的头部<nav>— 导航链接区域<main>— 页面主要内容区域<article>— 独立的文章内容<section>— 文档中的节/区块<aside>— 侧边栏内容<footer>— 页面或区块的底部<figure>和<figcaption>— 图文组合
📝 面试参考答案
使用语义化标签的好处包括:①提升代码可读性,让开发者和维护者更容易理解页面结构;②有利于SEO,搜索引擎能更好地理解页面内容;③提升无障碍访问,屏幕阅读器等辅助技术能更好地解析页面;④有利于多端适配,不同设备可以根据语义标签进行差异化渲染。
② Doctype的作用是什么?DOCTYPE声明有哪些?
DOCTYPE声明位于HTML文档的第一行,告知浏览器使用哪种HTML版本来解析文档。它不是HTML标签,而是一个指令。
常见的DOCTYPE声明包括:
<!-- HTML5 DOCTYPE -->
<!DOCTYPE html>
<!-- HTML 4.01 Strict -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<!-- XHTML 1.0 Strict -->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
📝 面试参考答案
DOCTYPE声明的主要作用是触发浏览器的标准模式渲染。如果没有DOCTYPE声明或声明不正确,浏览器会进入"怪异模式"(Quirks Mode),导致CSS盒模型、布局等行为与标准模式不同。HTML5的DOCTYPE声明最为简洁:<!DOCTYPE html>,它同时适用于HTML和XHTML。
③ HTML5新增了哪些新特性?
HTML5相比HTML4带来了许多重要改进,主要包括:
- 语义化标签:新增header、nav、main、article、section、aside、footer等
- 多媒体支持:新增audio、video、canvas、svg标签
- 表单增强:新增email、url、number、date、range、color等输入类型
- 本地存储:localStorage、sessionStorage
- Web API:WebSocket、Geolocation、Drag & Drop、History API
- 性能与集成:Service Worker、Web Workers、WebGL
- 移除元素:移除了basefont、big、center、font、strike、tt等
④ meta标签有哪些常用属性?viewport的作用是什么?
meta标签用于提供关于HTML文档的元数据,常用属性包括:
<!-- 字符编码 -->
<meta charset="UTF-8">
<!-- 视口设置(移动端适配关键) -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- SEO相关 -->
<meta name="description" content="页面描述">
<meta name="keywords" content="关键词1,关键词2">
<!-- 搜索引擎索引控制 -->
<meta name="robots" content="index, follow">
<!-- 兼容IE -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
📝 面试参考答案
viewport的content属性中,width=device-width表示视口宽度等于设备宽度,initial-scale=1.0表示初始缩放比例为1(不缩放)。这对于移动端网页的正确显示至关重要,没有viewport设置,移动端浏览器会以桌面视口宽度(通常980px)渲染页面,导致内容过小。
⑤ localStorage、sessionStorage和cookie的区别?
| 特性 | localStorage | sessionStorage | cookie |
|---|---|---|---|
| 存储大小 | 5MB+ | 5MB+ | 4KB |
| 生命周期 | 永久(手动清除) | 浏览器会话结束 | 可设置过期时间 |
| 服务端通信 | 不参与 | 不参与 | 每次请求自动携带 |
| 作用域 | 同源窗口共享 | 同源窗口内有效 | 可设置path/domain |
| API | getItem/setItem | getItem/setItem | document.cookie |
🎨 CSS面试题
CSS是前端面试中的必考内容,掌握以下核心知识点能帮助你应对大部分CSS面试题
① CSS盒模型有哪些?它们的区别是什么?
CSS盒模型分为两种:标准盒模型(content-box)和IE盒模型(border-box)。
- content-box(标准盒模型):width和height只包含content,不包含padding和border
- border-box(IE盒模型):width和height包含content + padding + border
/ 标准盒模型(默认) /
.box {
box-sizing: content-box;
width: 200px;
padding: 20px;
border: 5px solid;
/ 实际宽度 = 200 + 202 + 52 = 250px /
}
/ IE盒模型(推荐) /
.box {
box-sizing: border-box;
width: 200px;
padding: 20px;
border: 5px solid;
/ 实际宽度 = 200px(content自动缩减) /
}
/ 全局推荐使用border-box /
{
box-sizing: border-box;
}
📝 面试参考答案
面试中推荐全局使用box-sizing: border-box,因为这样计算元素尺寸时更加直观,width直接代表元素总宽度,避免了padding和border导致元素溢出父容器的常见问题。这也是CSS重置(reset)中常见的做法。
② CSS选择器的优先级如何计算?
CSS选择器优先级从高到低排列:
- 内联样式:1,0,0,0(直接在元素上写style属性)
- ID选择器:0,1,0,0(如 #header)
- 类选择器/属性选择器/伪类:0,0,1,0(如 .nav、[type="text"]、:hover)
- 元素选择器/伪元素:0,0,0,1(如 div、::before)
- 通配符/组合符:0,0,0,0(如 、+、~、空格)
优先级比较从左到右,高位为0时向低位借位。例如两个类选择器(0,0,2,0)优先级高于一个ID选择器(0,1,0,0)。
!important具有最高优先级,但应尽量避免使用,它会破坏正常的优先级规则,增加代码维护难度。
③ CSS中position属性的值有哪些?
CSS中position属性有5个值,每个值对应不同的定位行为:
- static(默认):元素按照正常文档流排列,top/right/bottom/left/z-index无效
- relative(相对定位):相对于自身原始位置偏移,不脱离文档流,占位保留
- absolute(绝对定位):相对于最近的非static定位祖先元素偏移,脱离文档流
- fixed(固定定位):相对于浏览器视口定位,脱离文档流,滚动时位置不变
- sticky(粘性定位):在跨越特定阈值前为relative,之后变为fixed
/ 绝对定位居中示例 /
.centered {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
📝 面试参考答案
absolute定位需要父元素有定位属性(非static),否则会继续向上查找,直到body。fixed定位始终相对于视口,不受父元素滚动影响。sticky定位是relative和fixed的结合体,需要设置top/left/right/bottom值才生效。
④ 如何实现CSS居中?(多种方案)
居中是CSS面试中最常见的问题之一,有多种实现方式:
/ 方案1:Flexbox居中(推荐) /
.parent {
display: flex;
justify-content: center;
align-items: center;
}
/ 方案2:Grid居中 /
.parent {
display: grid;
place-items: center;
}
/ 方案3:绝对定位 + transform /
.child {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
/ 方案4:margin auto(块级元素) /
.child {
width: 200px;
margin: 0 auto;
}
/ 方案5:table-cell居中 /
.parent {
display: table-cell;
text-align: center;
vertical-align: middle;
}
⑤ BFC是什么?如何触发BFC?
BFC(Block Formatting Context,块级格式化上下文)是CSS中的一个渲染规则,它决定了块级元素的布局方式和内部元素如何交互。触发BFC的条件包括:
- float的值不为none
- overflow的值不为visible
- display的值为flow-root、flex、inline-block、table-cell、table-caption
- position的值不为static或relative
📝 面试参考答案
BFC的主要作用:①清除浮动,父元素包含浮动子元素时,创建BFC可以自动计算高度;②防止margin重叠,相邻块级元素的垂直margin不会合并;③阻止元素被浮动元素覆盖,BFC区域不与浮动元素重叠。常用解决方案:父元素设置overflow: hidden或display: flow-root。
⑥ CSS常见布局方式有哪些?
前端面试中经常考察各种布局的实现方式,以下是主流布局方案:
- 浮动布局(Float):传统布局方式,通过float实现,需要清除浮动
- Flexbox布局:一维布局方案,适合导航栏、卡片列表等场景
- Grid布局:二维布局方案,适合复杂页面布局
- 绝对定位布局:通过position:absolute实现,适合弹窗、固定元素
- 圣杯布局 / 双飞翼布局:经典的三栏布局方案
/ Flexbox实现圣杯布局 /
.container {
display: flex;
min-height: 100vh;
}
.left { width: 200px; flex-shrink: 0; }
.right { width: 200px; flex-shrink: 0; }
.main { flex: 1; }
⚙️ JavaScript面试题
JavaScript是前端面试的核心内容,以下整理了初级前端面试中最高频的JS考点
① JavaScript的数据类型有哪些?如何判断数据类型?
JavaScript的数据类型分为基本类型和引用类型:
- 基本类型:undefined、null、boolean、number、string、symbol(ES6)、bigint(ES2020)
- 引用类型:Object(包括Array、Function、Date、RegExp等)
// 判断数据类型的方法
typeof undefined; // "undefined"
typeof null; // "object" ← 历史遗留bug
typeof 123; // "number"
typeof "abc"; // "string"
typeof true; // "boolean"
typeof Symbol(); // "symbol"
typeof []; // "object"
typeof {}; // "object"
typeof function(){}; // "function"
// 更准确的判断方法
Array.isArray([]); // true
Object.prototype.toString.call([]); // "[object Array]"
Object.prototype.toString.call({}); // "[object Object]"
📝 面试参考答案
typeof对null返回"object"是JavaScript的历史遗留bug。判断具体对象类型推荐使用Object.prototype.toString.call()方法,它返回"[object xxx]"格式,可以准确区分Array、Date、RegExp等内置对象。对于自定义对象,也可以通过constructor属性判断。
② 变量提升(Hoisting)是什么?
变量提升是指在JavaScript代码执行前,解释器会先将所有变量声明提升到当前作用域的顶部,但赋值操作保留在原位。
// 声明提升示例
console.log(a); // undefined(不是报错)
var a = 10;
// 等价于
var a;
console.log(a); // undefined
a = 10;
// let和const不存在变量提升
console.log(b); // ReferenceError
let b = 10;
// 函数声明也会被提升
foo(); // "hello"
function foo() {
console.log("hello");
}
📝 面试参考答案
var声明的变量和function声明的函数会被提升到作用域顶部。let和const存在"暂时性死区"(TDZ),在声明之前访问会报错。箭头函数不会被提升。理解变量提升有助于避免潜在的bug,这也是为什么ESLint推荐"先声明后使用"的原因。
③ 作用域和作用域链是什么?
作用域决定了变量的可访问范围。JavaScript中有三种作用域:
- 全局作用域:变量在整个程序中都可访问
- 函数作用域:变量在函数内部声明,只在函数内可访问
- 块级作用域(ES6):let和const声明的变量在块级作用域内有效
作用域链是指当访问一个变量时,JavaScript引擎会从当前作用域开始查找,如果找不到就沿着作用域链向上查找,直到全局作用域。
var global = "global";
function outer() {
var outerVar = "outer";
function inner() {
var innerVar = "inner";
console.log(innerVar); // "inner"(当前作用域)
console.log(outerVar); // "outer"(外层函数作用域)
console.log(global); // "global"(全局作用域)
}
inner();
}
outer();
④ 什么是闭包?闭包的应用场景有哪些?
闭包是指有权访问另一个函数作用域中变量的函数,通常由内部函数捕获外部函数的变量而形成。闭包的存在使得外部函数的变量在函数执行完毕后仍然保留在内存中。
// 闭包示例:计数器
function createCounter() {
let count = 0;
return {
increment: () => ++count,
decrement: () => --count,
getCount: () => count
};
}
const counter = createCounter();
counter.increment(); // 1
counter.increment(); // 2
counter.getCount(); // 2
// 闭包应用:数据封装
function createPrivateCounter(initial) {
let value = initial || 0;
return {
get: () => value,
set: (v) => { value = v; },
add: (n) => { value += n; }
};
}
// 闭包应用:防抖函数
function debounce(fn, delay) {
let timer = null;
return function(...args) {
clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, args);
}, delay);
};
}
📝 面试参考答案
闭包的核心特征是内部函数引用了外部函数的变量。应用场景包括:数据封装(私有变量)、函数柯里化、防抖节流、模块模式等。闭包的副作用是可能导致内存泄漏,因为被引用的变量不会被垃圾回收。
⑤ == 和 === 的区别?
- ==(宽松相等):进行比较前会进行类型转换,然后比较值
- ===(严格相等):不进行类型转换,类型和值都必须相等
1 == "1"; // true (字符串转数字)
1 === "1"; // false (类型不同)
0 == false; // true (false转数字为0)
0 === false; // false (类型不同)
null == undefined; // true
null === undefined; // false
NaN === NaN; // false (NaN不等于任何值,包括自身)
⑥ 原型和原型链是什么?
JavaScript中的每个对象都有一个内置的[[Prototype]]属性(可通过__proto__访问),指向它的原型对象。原型对象上定义的属性和方法可以被所有实例共享。
// 原型链示例
function Person(name) {
this.name = name;
}
Person.prototype.sayHello = function() {
return "Hello, I'm " + this.name;
};
const p1 = new Person("Alice");
console.log(p1.sayHello()); // "Hello, I'm Alice"
console.log(p1.hasOwnProperty('name')); // true
console.log(p1.hasOwnProperty('sayHello')); // false(在原型上)
// 原型链查找:p1 → Person.prototype → Object.prototype → null
📝 面试参考答案
原型链是JavaScript实现继承的核心机制。当访问对象的属性时,如果对象本身没有,就会沿着原型链向上查找,直到找到或到达原型链末端(null)。ES6的class语法只是原型继承的语法糖。理解原型链对于掌握JavaScript的面向对象编程至关重要。
⑦ Promise是什么?如何处理异步操作?
Promise是ES6引入的异步编程解决方案,表示一个异步操作的最终完成或失败。Promise有三种状态:Pending(进行中)、Fulfilled(已成功)、Rejected(已失败),状态一旦改变就不会再变。
// Promise基本用法
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("成功");
}, 1000);
});
promise.then(result => {
console.log(result); // "成功"
}).catch(error => {
console.error(error);
}).finally(() => {
console.log("无论成功失败都会执行");
});
// Promise.all - 并行执行
Promise.all([promise1, promise2, promise3])
.then(results => console.log(results))
.catch(err => console.error(err));
// async/await - 更优雅的异步写法
async function fetchData() {
try {
const data = await fetch('/api/data');
const json = await data.json();
console.log(json);
} catch (error) {
console.error(error);
}
}
⑧ 事件循环(Event Loop)机制是什么?
JavaScript是单线程语言,事件循环机制是其处理异步操作的核心机制。执行顺序为:
- 同步代码:直接执行
- 宏任务(Macrotask):setTimeout、setInterval、setImmediate、I/O、UI渲染
- 微任务(Microtask):Promise.then、MutationObserver、queueMicrotask
console.log("1"); // 同步
setTimeout(() => {
console.log("2"); // 宏任务
}, 0);
Promise.resolve().then(() => {
console.log("3"); // 微任务
});
console.log("4"); // 同步
// 输出顺序:1 → 4 → 3 → 2
📝 面试参考答案
事件循环的执行顺序:①执行所有同步代码;②执行完当前宏任务后,执行所有微任务;③执行完所有微任务后,再执行下一个宏任务。微任务的优先级高于宏任务,这是面试中的高频考点。
⑨ this指向问题
this的指向取决于函数的调用方式,以下是不同场景下的this指向规则:
// 1. 普通函数调用:this指向全局对象(浏览器中为window)
function foo() { console.log(this); }
foo(); // window
// 2. 方法调用:this指向调用该方法的对象
const obj = {
name: "Alice",
sayName: function() { console.log(this.name); }
};
obj.sayName(); // "Alice"
// 3. 构造函数调用:this指向新创建的对象
function Person(name) { this.name = name; }
const p = new Person("Bob");
// 4. 箭头函数:this指向定义时外层函数的this
const obj2 = {
name: "Charlie",
getName: () => console.log(this.name) // 外层this(window)
};
// 5. call/apply/bind:显式绑定this
const person = { name: "Dave" };
foo.call(person); // person
🟢 Vue.js面试题
Vue是目前国内使用最广泛的前端框架之一,以下是Vue相关的面试高频考点
① Vue的生命周期有哪些?
Vue实例从创建到销毁的完整过程称为生命周期,每个阶段都有对应的钩子函数:
// Vue 2 生命周期
beforeCreate → created → beforeMount → mounted →
beforeUpdate → updated → beforeDestroy → destroyed
// Vue 3 生命周期(Composition API)
setup → onBeforeMount → onMounted →
onBeforeUpdate → onUpdated → onBeforeUnmount → onUnmounted
// 常用钩子说明
created: 实例创建完成,数据观测和事件配置完成,可访问data/methods
mounted: DOM挂载完成,可操作DOM元素
beforeDestroy: 实例销毁之前,可执行清理工作(清除定时器、取消订阅)
updated: 数据更新导致DOM重新渲染后触发
📝 面试参考答案
面试中常问created和mounted的区别:created时DOM尚未生成,适合发起数据请求;mounted时DOM已挂载,适合操作DOM。Vue 3中beforeDestroy和destroyed分别对应onBeforeUnmount和onUnmounted。
② Vue的响应式原理是什么?
Vue 2使用Object.defineProperty实现响应式,Vue 3使用Proxy实现响应式:
// Vue 2 响应式原理(简化版)
function defineReactive(obj, key, val) {
const dep = new Dep();
Object.defineProperty(obj, key, {
get() {
if (Dep.target) dep.addSub(Dep.target); // 收集依赖
return val;
},
set(newVal) {
if (newVal !== val) {
val = newVal;
dep.notify(); // 通知更新
}
}
});
}
// Vue 3 响应式原理(简化版)
const reactive = (obj) => {
return new Proxy(obj, {
get(target, key) {
track(target, key); // 收集依赖
return target[key];
},
set(target, key, value) {
target[key] = value;
trigger(target, key); // 触发更新
}
});
};
③ Vue中key的作用是什么?
key是Vue中列表渲染的重要属性,它帮助Vue识别每个节点的身份,从而高效地重新渲染DOM。
📝 面试参考答案
key的作用:①帮助Virtual DOM算法准确识别节点,提高渲染性能;②保持组件状态,当列表顺序变化时,有key的组件不会重新创建,而是复用;③避免不必要的DOM操作。key应该是唯一且稳定的,不建议使用index作为key(当列表可排序或增删时会导致问题)。
④ Vue和React的区别?
| 对比项 | Vue | React |
|---|---|---|
| 模板语法 | 模板语法(HTML+JS) | JSX(JS中写HTML) |
| 响应式 | 自动响应式(defineProperty/Proxy) | 手动setState/useState |
| 数据流 | 单向数据流 + 双向绑定(v-model) | 单向数据流 |
| 组件通信 | props、$emit、provide/inject、Vuex | props、context、Redux |
| 学习曲线 | 相对平缓 | 相对陡峭 |
| 包体积 | 较小(约33KB) | 较大(React + ReactDOM约42KB) |
⚛️ React面试题
React是另一款主流前端框架,以下是React相关的面试高频考点
① React的生命周期有哪些?
React Class组件的生命周期分为三个阶段:
- 挂载阶段:constructor → static getDerivedStateFromProps → render → componentDidMount
- 更新阶段:static getDerivedStateFromProps → shouldComponentUpdate → render → getSnapshotBeforeUpdate → componentDidUpdate
- 卸载阶段:componentWillUnmount
React Hooks(函数组件)中,useEffect可以模拟大部分生命周期:
// 模拟 componentDidMount
useEffect(() => {
// 挂载时执行
return () => {
// 卸载时执行(清理)
};
}, []);
// 模拟 componentDidUpdate
useEffect(() => {
// 每次渲染后执行
}, [dep]); // 依赖数组控制触发时机
② React中Virtual DOM是什么?Diff算法原理?
Virtual DOM是React对真实DOM的轻量级JavaScript对象表示。当状态变化时,React会:
- 用Virtual DOM重建整个UI树
- 通过Diff算法比较新旧Virtual DOM
- 计算出最小变更集
- 批量更新真实DOM
Diff算法采用三层策略:①Tree Diff:只比较同层节点,不跨层比较;②Component Diff:同类组件复用,不同类组件直接销毁重建;③Element Diff:通过key识别节点,支持三种操作:insert、update、delete。
📝 面试参考答案
Virtual DOM的核心价值在于性能优化和跨平台能力。虽然每次渲染都要重建Virtual DOM,但通过Diff算法最小化了真实DOM操作,避免了频繁的DOM操作带来的性能损耗。React 18引入的Fiber架构进一步实现了可中断的渲染。
③ React Hooks有哪些?规则是什么?
常用Hooks包括:
- useState:状态管理
- useEffect:副作用处理
- useContext:上下文访问
- useRef:DOM引用和持久化值
- useMemo:记忆化计算
- useCallback:记忆化函数
- useReducer:复杂状态管理
// Hooks使用规则
// 规则1:只在顶层调用,不要在循环/条件/嵌套函数中调用
// 规则2:只在React函数组件或自定义Hook中调用
const [count, setCount] = useState(0);
const doubled = useMemo(() => count 2, [count]);
const handleClick = useCallback(() => {
console.log(count);
}, [count]);
🔧 工程化面试题
前端工程化是现代前端开发的重要能力,以下是相关面试考点
① Webpack的核心概念有哪些?
Webpack的核心概念包括:
- Entry(入口):Webpack执行构建的起点
- Output(输出):构建结果的输出位置和命名
- Loader(加载器):处理非JS文件(如babel-loader、css-loader)
- Plugin(插件):扩展Webpack功能(如HtmlWebpackPlugin、CleanWebpackPlugin)
- Module(模块):Webpack将一切视为模块
- Chunk(代码块):由多个模块组合而成的代码块
- Mode(模式):development、production、none
// 基础Webpack配置示例
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.[contenthash:8].js',
path: path.resolve(__dirname, 'dist'),
clean: true
},
module: {
rules: [
{ test: /\.js$/, use: 'babel-loader', exclude: /node_modules/ },
{ test: /\.css$/, use: ['style-loader', 'css-loader'] },
{ test: /\.(png|jpg|gif)$/, type: 'asset' }
]
},
optimization: {
splitChunks: {
chunks: 'all'
}
}
};
② Git常用命令有哪些?
git init— 初始化仓库git clone— 克隆远程仓库git add— 添加到暂存区git commit— 提交到本地仓库git push— 推送到远程仓库git pull— 拉取远程更新git branch— 查看/创建分支git checkout— 切换分支git merge— 合并分支git rebase— 变基(线性历史)git stash— 暂存当前修改git log— 查看提交历史
③ ESLint和Prettier的区别?
- ESLint:代码质量检查工具,检测潜在错误和代码风格问题,可配置规则
- Prettier:代码格式化工具,统一代码排版风格,忽略语义分析
两者通常配合使用:ESLint保证代码质量和一致性,Prettier保证代码格式美观。在VS Code中可通过设置实现保存时自动格式化。
🌐 计算机网络面试题
网络知识是前端开发的必备基础,以下是网络相关的高频面试题
① HTTP和HTTPS的区别?
| 对比项 | HTTP | HTTPS |
|---|---|---|
| 端口 | 80 | 443 |
| 安全性 | 明文传输,不安全 | 加密传输,安全 |
| 证书 | 不需要 | 需要SSL/TLS证书 |
| 性能 | 较快 | SSL握手增加延迟 |
| SEO | 普通 | 搜索引擎优先收录 |
📝 面试参考答案
HTTPS = HTTP + SSL/TLS加密层。SSL/TLS通过非对称加密交换密钥,然后使用对称加密传输数据,兼顾安全性和性能。HTTPS防止了中间人攻击、数据窃听和篡改。Google已将HTTPS作为SEO排名因素之一。
② 常见的HTTP状态码有哪些?
- 1xx:信息性状态码(如100 Continue)
- 2xx:成功(200 OK、201 Created、204 No Content)
- 3xx:重定向(301 Moved Permanently、302 Found、304 Not Modified)
- 4xx:客户端错误(400 Bad Request、401 Unauthorized、403 Forbidden、404 Not Found)
- 5xx:服务器错误(500 Internal Server Error、502 Bad Gateway、503 Service Unavailable)
③ GET和POST的区别?
- GET:用于获取数据,参数放在URL中,有长度限制,可缓存,不安全
- POST:用于提交数据,参数放在请求体中,无长度限制,不缓存,相对安全
- 幂等性:GET是幂等的(多次请求结果相同),POST不是幂等的
④ 跨域解决方案有哪些?
同源策略(协议+域名+端口相同)是浏览器的安全机制,跨域是指请求不同源的服务器。常见解决方案:
- CORS(跨域资源共享):后端设置Access-Control-Allow-Origin响应头(最常用)
- JSONP:利用script标签不受同源策略限制的特性(仅支持GET)
- 代理:通过开发服务器代理转发请求(如webpack devServer proxy)
- document.domain:适用于主域名相同但子域名不同的情况
- postMessage:用于跨窗口通信
🚀 性能优化面试题
前端性能优化是衡量开发者能力的重要指标,以下是性能优化相关的高频考点
① 前端性能优化的常见手段有哪些?
📦 资源优化
- 图片压缩(WebP格式、懒加载)
- 代码压缩和混淆(UglifyJS、Terser)
- 代码分割(Code Splitting)
- Tree Shaking(移除未使用代码)
- Gzip/Brotli压缩
⚡ 渲染优化
- 减少重排和重绘
- 使用CSS3动画(GPU加速)
- 防抖和节流
- 虚拟列表(长列表优化)
- 减少DOM节点数量
② 如何测量前端性能?
Web Vitals是Google提出的核心性能指标:
- LCP(Largest Contentful Paint):最大内容绘制时间,目标<2.5s
- FID(First Input Delay):首次输入延迟,目标<100ms
- CLS(Cumulative Layout Shift):累积布局偏移,目标<0.1
- FCP(First Contentful Paint):首次内容绘制,目标<1.8s
- TTFB(Time to First Byte):首字节时间,目标<0.8s
测量工具:Chrome DevTools(Lighthouse)、WebPageTest、Google PageSpeed Insights、Performance API。
③ 懒加载和预加载有什么区别?
// 图片懒加载
const img = document.createElement('img');
img.dataset.src = 'image.jpg'; // 使用data-src存储真实地址
// IntersectionObserver实现懒加载
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
observer.unobserve(img);
}
});
});
// 预加载
<link rel="preload" href="font.woff2" as="font" type="font/woff2">
// prefetch(浏览器空闲时加载)
<link rel="prefetch" href="next-page.js">
// prerender(预渲染整个页面)
<link rel="prerender" href="next-page.html">
📝 面试参考答案
懒加载是延迟加载,在需要时才加载资源(如滚动到可视区域才加载图片);预加载是提前加载,在浏览器空闲时预先加载可能需要的资源。两者目的不同:懒加载减少初始加载时间,预加载加速后续页面访问。
❓ 高频面试题FAQ
以下是初级前端面试中最常出现的10个核心问题及其深度解析
Q1:CSS中如何清除浮动?
清除浮动是CSS面试中的经典问题。浮动元素会导致父元素高度塌陷,需要通过以下方式清除:
/ 方案1:额外标签法(不推荐) /
.clearfix::after {
content: '';
display: block;
clear: both;
}
/ 方案2:overflow法(常用) /
.parent {
overflow: hidden; / 触发BFC /
}
/ 方案3:BFC法 /
.parent {
display: flow-root; / 现代方案 /
}
/ 方案4:双伪元素法(最推荐) /
.clearfix::before,
.clearfix::after {
content: '';
display: table;
}
.clearfix::after {
clear: both;
}
Q2:JavaScript中深拷贝和浅拷贝的区别?
// 浅拷贝(只拷贝一层)
const obj1 = { a: 1, b: { c: 2 } };
const obj2 = { ...obj1 }; // 或 Object.assign({}, obj1)
obj2.b.c = 3;
console.log(obj1.b.c); // 3(被影响了)
// 深拷贝方案1:JSON.parse/stringify(有局限)
const obj3 = JSON.parse(JSON.stringify(obj1));
// 深拷贝方案2:递归实现
function deepClone(obj, map = new WeakMap()) {
if (obj === null || typeof obj !== 'object') return obj;
if (map.has(obj)) return map.get(obj);
const clone = Array.isArray(obj) ? [] : {};
map.set(obj, clone);
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
clone[key] = deepClone(obj[key], map);
}
}
return clone;
}
// 深拷贝方案3:structuredClone(浏览器原生)
const obj4 = structuredClone(obj1);
Q3:防抖和节流有什么区别?
// 防抖:多次触发只执行最后一次
function debounce(fn, delay) {
let timer = null;
return function(...args) {
clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, args), delay);
};
}
// 适用场景:搜索输入框、窗口resize
// 节流:固定时间间隔内只执行一次
function throttle(fn, interval) {
let lastTime = 0;
return function(...args) {
const now = Date.now();
if (now - lastTime >= interval) {
lastTime = now;
fn.apply(this, args);
}
};
}
// 适用场景:滚动加载、按钮防重复点击
Q4:什么是同源策略?如何跨域?
同源策略是浏览器的核心安全机制,要求协议、域名、端口完全相同。跨域解决方案:
- CORS:后端配置Access-Control-Allow-Origin(最常用)
- JSONP:利用script标签(仅GET)
- 代理:开发服务器代理(webpack devServer proxy)
- postMessage:跨窗口通信
Q5:Vue中computed和watch的区别?
- computed:计算属性,有缓存,依赖变化时重新计算,适合一个值依赖多个值
- watch:侦听器,监听特定数据变化时执行异步或开销较大的操作,适合一个值影响多个值
// computed - 有缓存,只有依赖变化时才重新计算
computed: {
fullName() {
return this.firstName + ' ' + this.lastName;
}
}
// watch - 监听变化,执行副作用
watch: {
question(newVal, oldVal) {
this.getAnswer(newVal); // 异步操作
}
}
Q6:JavaScript中数组常用方法有哪些?
// 增删改
arr.push(...items) // 末尾添加
arr.pop() // 末尾删除
arr.unshift(...items) // 开头添加
arr.shift() // 开头删除
arr.splice(start, deleteCount, ...items) // 增删改
// 遍历
arr.forEach((item, index) => {})
arr.map(item => item 2)
arr.filter(item => item > 0)
arr.reduce((acc, item) => acc + item, 0)
arr.find(item => item > 0)
arr.findIndex(item => item > 0)
arr.some(item => item > 0)
arr.every(item => item > 0)
// 排序和反转
arr.sort((a, b) => a - b)
arr.reverse()
// 连接和分割
arr.concat([1, 2])
arr.slice(start, end)
[...arr1, ...arr2] // 展开运算符
Q7:HTTP缓存策略有哪些?
- 强缓存:不发送请求,直接从缓存读取
- Cache-Control: max-age=3600(优先级最高)
- Expires: 绝对过期时间(HTTP/1.0)
- 协商缓存:发送请求到服务器验证
- Etag / If-None-Match(基于资源内容哈希)
- Last-Modified / If-Modified-Since(基于修改时间)
📝 面试参考答案
缓存策略优先级:强缓存命中 → 不发送请求;协商缓存命中 → 返回304,使用本地缓存;都不命中 → 返回200,更新缓存。Cache-Control优先级高于Expires,Etag优先级高于Last-Modified。
Q8:Vue中$nextTick的作用是什么?
nextTick。
// 数据变化后操作DOM
this.message = 'updated';
this.$nextTick(() => {
// DOM已更新
const el = this.$refs.myElement;
el.focus();
});
// Vue 3 Composition API
import { nextTick } from 'vue';
await nextTick();
Q9:JavaScript中call、apply、bind的区别?
const obj1 = { name: 'Alice' };
const obj2 = { name: 'Bob' };
function greet(greeting) {
return greeting + ', I am ' + this.name;
}
// call:立即执行,参数逐个传递
greet.call(obj1, 'Hello'); // "Hello, I am Alice"
// apply:立即执行,参数以数组形式传递
greet.apply(obj1, ['Hello']); // "Hello, I am Alice"
// bind:返回新函数,不立即执行
const newGreet = greet.bind(obj1);
newGreet('Hello'); // "Hello, I am Alice"
Q10:如何实现一个Promise?
class MyPromise {
constructor(executor) {
this.state = 'pending';
this.value = undefined;
this.reason = undefined;
this.callbacks = [];
const resolve = (value) => {
if (this.state === 'pending') {
this.state = 'fulfilled';
this.value = value;
this.callbacks.forEach(cb => cb.onFulfilled(value));
}
};
const reject = (reason) => {
if (this.state === 'pending') {
this.state = 'rejected';
this.reason = reason;
this.callbacks.forEach(cb => cb.onRejected(reason));
}
};
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
then(onFulfilled, onRejected) {
return new MyPromise((resolve, reject) => {
this.callbacks.push({
onFulfilled: (value) => {
try {
const result = onFulfilled ? onFulfilled(value) : value;
resolve(result);
} catch (e) {
reject(e);
}
},
onRejected: (reason) => {
try {
const result = onRejected ? onRejected(reason) : reject(reason);
resolve(result);
} catch (e) {
reject(e);
}
}
});
});
}
}
💡 面试技巧与备考建议
掌握知识点只是第一步,面试技巧和备考策略同样重要。以下是经过验证的实用建议:
📚 基础知识巩固
系统复习HTML、CSS、JavaScript基础,确保每个概念都能清晰解释。建议阅读《JavaScript高级程序设计》(红宝书)前10章,完成所有课后习题。
🔧 框架深入学习
选择Vue或React深入学习,理解核心原理(响应式、虚拟DOM、组件通信)。阅读官方文档,完成官方教程项目,理解框架的设计哲学。
🏗️ 工程化实践
学习Webpack/Vite配置,了解ESLint/Prettier/Stylelint工具链,掌握Git工作流。尝试搭建一个完整的前端项目,从0到1经历完整的开发流程。
🎯 模拟面试训练
找同伴进行模拟面试,或者对着镜子练习表达。重点训练:①用简洁语言解释复杂概念 ②手写代码的能力 ③遇到不会的问题如何思考。
📝 项目经验梳理
准备2-3个完整项目,能用STAR法则(情境-任务-行动-结果)清晰描述项目中的技术选型、难点解决和个人贡献。这是面试中最能体现能力的部分。
🎤 面试中的表达技巧
- 先说结论:回答问题时先给出核心答案,再展开细节
- 举例说明:用实际项目中的例子来佐证你的理解
- 承认不足:遇到不会的问题,坦诚说明并表示愿意学习
- 展示思考:即使答案不完全正确,展示你的思考过程也很重要
- 控制节奏:不要急于回答,先思考10-15秒再开口
- 主动引导:将话题引向你熟悉的领域,展示你的优势
📋 面试前准备清单
- ☑ 准备好个人简历,突出项目经验和技术栈
- ☑ 复习基础概念,特别是HTML/CSS/JS核心考点
- ☑ 准备1-2个可以深入讲解的项目案例
- ☑ 练习手写常见代码(防抖节流、深拷贝、Promise等)
- ☑ 了解目标公司的技术和业务方向
- ☑ 准备反问面试官的问题(团队规模、技术栈、发展方向等)
- ☑ 测试网络和设备,确保线上面试环境稳定
🔍 面试官常问的软性问题
- 「为什么选择前端开发?」—— 展示热情和职业认知
- 「你最近在学习什么?」—— 展示学习能力和技术敏感度
- 「遇到最难的技术问题是什么?怎么解决的?」—— 展示问题解决能力
- 「你如何看待团队协作?」—— 展示沟通能力和团队精神
- 「你的职业规划是什么?」—— 展示目标感和稳定性
🔗 网友们还关心
除了初级前端面试题本身,求职者通常还会关注以下与前端职业发展密切相关的周边知识
📊 前端薪资行情
2024年初级前端开发工程师的薪资范围因城市而异:
- 一线城市(北上广深):8K-15K/月
- 新一线城市(杭州/成都/武汉等):6K-12K/月
- 二三线城市:5K-9K/月
薪资受技术栈深度、项目经验、学历背景等因素影响。掌握Vue3/React18+TypeScript+工程化的开发者更具竞争力。
📚 推荐学习资源
系统学习前端知识的优质资源:
- MDN Web Docs(权威文档)
- freeCodeCamp(免费实战)
- 掘金社区(技术文章)
- 阮一峰的网络日志(教程)
- 《JavaScript高级程序设计》(书籍)
- Vue/React官方文档(最佳实践)
💼 前端职业路径
前端工程师的典型发展路径:
- 初级前端 → 中级前端 → 高级前端
- 前端专家 / 技术负责人
- 全栈工程师(学习Node.js/后端)
- 前端架构师
- 技术管理(前端团队Leader/总监)
🛠️ 前端工具链
现代前端开发必备的工具:
- 编辑器:VS Code(推荐)
- 包管理:npm / yarn / pnpm
- 构建工具:Vite(推荐)/ Webpack / Rollup
- 代码规范:ESLint + Prettier
- 调试工具:Chrome DevTools
- 版本控制:Git + GitHub/GitLab
🌐 前端技术趋势
2024年前端技术发展趋势:
- TypeScript成为标配
- Vue3 + Composition API普及
- React18 + Server Components
- SSR/SSG框架(Nuxt/Next)
- Monorepo工具(pnpm workspace)
- AI辅助编程(Copilot等)
📝 简历撰写建议
前端工程师简历的关键要素:
- 技术栈清晰列出(HTML/CSS/JS/Vue/React等)
- 项目经验用数据量化成果
- 突出解决问题的能力和技术深度
- 附上GitHub链接和技术博客
- 控制在一页A4纸内