前端核心基础汇总

一、JavaScript 核心基础

1. 闭包 (Closure)
  • 定义 :函数和其周围状态(词法环境)的引用捆绑在一起构成闭包。简单说,就是内部函数可以访问外部函数的变量,即使外部函数已经执行完毕。
  • 作用:数据私有化、延长变量生命周期、柯里化。
  • 缺点:滥用会导致内存泄漏(变量无法被回收)。
2. 原型链 (Prototype Chain)
  • 机制 :每个对象都有一个 __proto__ 指向它的原型对象 (prototype)。当访问一个属性时,如果自身没有,就会沿着 __proto__ 向上查找,直到 null。这条链条就是原型链。
  • 终点 :Object.prototype.__proto__ === null。
3. 数据类型
  • 基本类型 (栈) :String, Number, Boolean, Null, Undefined, Symbol, BigInt。按值访问,复制是复制值。
  • 引用类型 (堆) :Object, Array, Function, Date 等。按引用访问,复制是复制地址(指针)。
4. 冒泡排序 (Bubble Sort)
  • 原理:重复遍历数组,比较相邻元素,如果顺序错误就交换。每一轮将最大的元素"浮"到末尾。
  • 复杂度:时间 O(n2)O(n2) ,空间 O(1)O(1) 。
  • 代码简述:双重循环,外层控制轮数,内层控制比较交换。
5. 递归算法
  • 定义:函数在内部调用自身。
  • 关键 :必须有终止条件(基准情况),否则会栈溢出。
  • 应用:阶乘、斐波那契数列、深拷贝、树形结构遍历。
6. 数组排序
  • 原生方法 :array.sort((a, b) => a - b)。注意默认是按字符串 Unicode 排序,数字需传比较函数。
  • 常见算法:冒泡、选择、插入、快速排序 (Quick Sort, 最常用,平均 O(nlog⁡n)O(nlogn) )、归并排序。
7. 浅拷贝 vs 深拷贝
  • 浅拷贝 :只复制第一层属性。如果属性是引用类型,复制的是地址(改一处全变)。
    • 方法:Object.assign(), 展开运算符 {...obj}, Array.slice().
  • 深拷贝 :递归复制所有层级,生成全新的对象,互不影响。
    • 方法:JSON.parse(JSON.stringify(obj)) (有缺陷,不能处理函数/undefined/date), structuredClone() (新API), 手写递归,lodash _.cloneDeep。
8. this 的指向
  • 默认绑定 :独立函数调用,指向全局 (window/undefined)。
  • 隐式绑定 :obj.fn(),指向 obj。
  • 显式绑定 :call, apply, bind,指向指定的对象。
  • new 绑定:构造函数调用,指向新创建的实例。
  • 箭头函数 :没有自己的 this ,继承自上一层作用域的 this。
9. 继承
  • 原型链继承:子类原型 = 父类实例。缺点:引用属性共享。
  • 构造函数继承 :Parent.call(this)。缺点:方法无法复用。
  • 组合继承:原型链 + 构造函数(最常用)。
  • ES6 Class 继承 :class Child extends Parent,底层仍是原型链,但语法更清晰。
10. 判断是不是原型的方法 / for in 遍历原型
  • 判断原型 :A.prototype.isPrototypeOf(B) 或 B instanceof A。

  • for in 遍历 :会 遍历对象自身可枚举属性 以及 原型链上的可枚举属性。

  • 过滤原型 :通常配合 hasOwnProperty 使用:javascript

    javascript 复制代码
    for (let key in obj) {
      if (obj.hasOwnProperty(key)) { ... } // 只处理自身属性
    }
11. 遍历数组/对象
  • 数组 :for, forEach, map (返回新数组), filter, reduce, for...of (推荐,可中断)。
  • 对象 :for...in (含原型), Object.keys(), Object.values(), Object.entries()。
12. 事件循环机制 (Event Loop)
  • 流程 :
    1. 执行同步代码(调用栈)。
    2. 异步任务放入任务队列(宏任务:setTimeout, I/O; 微任务:Promise, nextTick)。
    3. 调用栈清空后,先执行完所有微任务。
    4. 再执行一个宏任务。
    5. 循环往复。
  • 关键点:微任务优先级高于宏任务。

二、浏览器、网络与安全

13. 输入 URL 到页面展示的详细过程
  1. DNS 解析:域名 -> IP 地址。
  2. TCP 连接:三次握手。
  3. 发送 HTTP 请求。
  4. 服务器处理并返回响应。
  5. 浏览器渲染 :
    • 构建 DOM 树。
    • 构建 CSSOM 树。
    • 生成渲染树 (Render Tree)。
    • 布局 (Layout/Reflow)。
    • 绘制 (Paint)。
  6. TCP 断开:四次挥手。
14. 常见的状态码
  • 200:成功。
  • 301/302:永久/临时重定向。
  • 304:资源未修改(使用缓存)。
  • 400:请求参数错误。
  • 401:未授权。
  • 403:禁止访问。
  • 404:资源不存在。
  • 500:服务器内部错误。
  • 502/503/504:网关错误/服务不可用/超时。
15. 跨域解决
  • 原因:浏览器的同源策略(协议、域名、端口任一不同即跨域)。
  • 解决方案 :
    • CORS (后端设置 Access-Control-Allow-Origin) - 最主流。
    • Nginx 反向代理 - 生产环境常用。
    • Webpack/Vite 开发代理 (proxy)。
    • postMessage (窗口间通信)。
    • (旧方案:JSONP,仅支持 GET)。
16. HTTP 缓存
  • 强缓存 :不发送请求,直接用本地。
    • 头:Cache-Control: max-age=3600, Expires。
  • 协商缓存 :发送请求,服务器判断是否过期(返回 304)。
    • 头:Last-Modified / If-Modified-Since (基于时间),Etag / If-None-Match (基于内容哈希,更精准)。
17. XSS 攻击 vs CSRF 攻击
  • XSS (跨站脚本攻击) :
    • 原理:注入恶意脚本到网页,用户浏览时执行,窃取 Cookie 等。
    • 防御:转义输入输出,CSP (内容安全策略),HttpOnly Cookie。
  • CSRF (跨站请求伪造) :
    • 原理:诱导用户在已登录状态下访问恶意网站,向后端发送请求(如转账)。
    • 防御 :SameSite Cookie,验证 Referer/Origin,CSRF Token。
  • 区别:XSS 是借用户的浏览器执行脚本;CSRF 是借用户的身份发送请求。
18. 怎么打断点
  • Sources 面板:点击行号。
  • 代码中 :debugger; 语句。
  • DOM 断点:Elements 面板 -> 右键节点 -> Break on。
  • XHR/Fetch 断点:Sources 面板右侧 XHR Breakpoints。
19. Git 冲突怎么解决
  1. git pull 或 git merge 时发现冲突。
  2. 打开冲突文件,找到 <<<<<<<, =======, >>>>>>> 标记。
  3. 手动保留需要的代码,删除标记符号。
  4. git add <file> 标记为已解决。
  5. git commit 完成合并。

三、CSS、HTML5 与工程化

20. H5 (HTML5) & C3 (CSS3)
  • H5 新特性 :语义化标签 (header, footer),多媒体 (video, audio),存储 (localStorage, sessionStorage),绘图 (Canvas, SVG),地理定位,Web Workers。
  • C3 新特性 :选择器增强,盒模型 (box-sizing),Flex/Grid 布局,动画 (transition, animation, transform),媒体查询 (响应式),变量 (--color)。
21. Less/Sass 用法和编译
  • 用法 :嵌套写法、变量 ($color)、混合 (mixin)、函数、继承 (@extend)。
  • 编译:浏览器不直接识别,需通过构建工具 (Webpack Loader, Vite Plugin) 或 CLI 编译成 CSS。
22. 兼容性解决
  • CSS :加厂商前缀 (-webkit-, -moz-),使用 Autoprefixer 插件自动添加;Polyfill。
  • JS :Babel 转译 ES6+ 为 ES5;引入核心 Polyfill (core-js)。
  • 策略:渐进增强,优雅降级。
23. Rem 原理 & 移动端适配
  • Rem :相对于根元素 (html) 的 font-size。
  • 原理 :通过 JS 或 CSS 媒体查询,根据屏幕宽度动态设置 html 的 font-size。例如:屏幕宽 375px,设 html font-size 为 37.5px,则 1rem = 37.5px。设计稿 100px -> 写 2.66rem。
  • 方案 :flexible.js 方案,或 vw/vh 单位(更现代,1vw = 1% 屏幕宽)。
24. 性能优化
  • 网络:压缩资源 (Gzip/Brotli),图片优化 (WebP, 懒加载),CDN 加速,减少 HTTP 请求 (合并/雪碧图),HTTP/2。
  • 渲染 :减少重排重绘,使用 will-change,虚拟列表 (长列表),防抖节流。
  • 代码:路由懒加载,组件懒加载,Tree Shaking,移除无用代码。
  • 缓存:合理利用强缓存和协商缓存。

四、Vue 框架专项

25. 生命周期 (Vue 2 vs Vue 3)
  • Vue 2 : beforeCreate, created, beforeMount, mounted, beforeUpdate, updated, beforeDestroy, destroyed。
  • Vue 3 (Composition API) : setup() 替代了 beforeCreate 和 created。其他钩子前加 on,如 onMounted, onUpdated, onBeforeUnmount。
  • 常用 :created/mounted (发起请求), beforeUnmount (清除定时器/解绑事件)。
26. 传值的方式
  • 父传子 :props。
  • 子传父 :$emit。
  • 兄弟/跨级 :EventBus (Vue2), Provide/Inject, Vuex/Pinia, $attrs/$listeners。
  • 透传 :$attrs (Vue3 默认开启,Vue2 需配置 inheritAttrs)。
27. 计算属性 (Computed) vs 监听属性 (Watch)
  • Computed :
    • 有缓存,依赖不变不重新计算。
    • 必须return 一个值。
    • 不支持异步。
    • 适用:一个值受多个值影响(多对一)。
  • Watch :
    • 无缓存,数据变就执行。
    • 支持异步操作。
    • 可以监听对象深层变化 (deep: true)。
    • 适用:一个值变化影响多个操作(一对多),或需要执行副作用。
28. Vuex (状态管理)
  • 核心概念 :
    • State:存放数据。
    • Getters:数据的计算属性。
    • Mutations:唯一修改 State 的地方(同步)。
    • Actions:处理异步逻辑,提交 Mutations。
    • Modules:模块化。
  • Vue 3 趋势 :推荐使用 Pinia (更轻量,去掉了 Mutation,支持 TS 更好)。
29. 数据双向绑定原理
  • Vue 2 :Object.defineProperty()。
    • 缺点:无法监听对象属性的新增/删除,无法监听数组下标变化(需用 $set 或替换方法)。
  • Vue 3 :Proxy。
    • 优点:直接代理整个对象,完美监听增删改查,性能更好。
30. v-show vs v-if
  • v-if :
    • 真正销毁/创建 DOM 节点。
    • 切换开销大。
    • 支持 <template> 分组。
    • 适用:条件很少改变,或初始不显示。
  • v-show :
    • 始终渲染,通过 CSS display: none 控制显示。
    • 切换开销小。
    • 不支持 <template>。
    • 适用:频繁切换显示状态。
31. keep-alive
  • 作用 :内置组件,用于缓存动态组件 或 router-view,保留组件状态,避免重复渲染。
  • 生命周期 :被缓存的组件会多出 activated (激活) 和 deactivated (停用) 钩子。
  • 属性 :include (缓存谁), exclude (不缓存谁), max (最大缓存数)。
32. nextTick
  • 原理 :将回调函数延迟到下一次 DOM 更新循环结束之后执行。
  • 场景 :当你修改了数据,想立即获取更新后的 DOM 元素(因为 DOM 更新是异步的),就需要用 this.$nextTick(() => { ... }) 或 await nextTick()。

一、怎么实现 apply 函数?

Function.prototype.apply 的作用是改变函数运行时的 this 指向 ,并接收一个参数数组来调用函数。

核心思路
  1. 处理上下文 :如果传入的 thisArg 是 null 或 undefined,在非严格模式下指向全局对象(浏览器是 window),严格模式下为 undefined。
  2. 临时绑定 :将当前函数(调用 apply 的函数)作为传入对象的一个临时属性。
  3. 执行函数 :通过对象调用该临时属性(此时 this 指向该对象),并使用展开运算符 ... 传递参数数组。
  4. 清理现场:删除临时属性,防止污染原对象。
  5. 返回结果:返回函数执行的结果。
代码实现
javascript 复制代码
Function.prototype.myApply = function(context, argsArray) {
  // 1. 处理 context:如果是 null/undefined,指向全局对象 (window)
  // 注意:在严格模式下 this 可能是 undefined,这里做简单兼容处理
  if (context === null || context === undefined) {
    context = typeof window !== 'undefined' ? window : globalThis;
  } else {
    // 如果传入的是基本类型,需要转换为对象 (如 'str' -> new String('str'))
    context = Object(context);
  }

  // 2. 获取调用 myApply 的函数本身
  const fn = this;

  // 3. 定义一个唯一的 Symbol 键,防止覆盖对象原有属性
  const fnKey = Symbol('fn');

  // 4. 将函数挂载到 context 上
  context[fnKey] = fn;

  // 5. 执行函数
  let result;
  if (!argsArray) {
    // 如果没有传参数数组,直接调用
    result = context[fnKey]();
  } else {
    // 如果有参数数组,使用展开运算符传递
    // 需确保 argsArray 是类数组对象,否则报错
    if (!Array.isArray(argsArray) && !(argsArray instanceof Object)) {
       throw new TypeError('CreateListFromArrayLike called on non-object');
    }
    result = context[fnKey](...argsArray);
  }

  // 6. 删除临时属性
  delete context[fnKey];

  // 7. 返回结果
  return result;
};
测试用例
javascript 复制代码
function greet(greeting, punctuation) {
  return greeting + ', ' + this.name + punctuation;
}

const person = { name: 'Alice' };

console.log(greet.myApply(person, ['Hello', '!'])); 
// 输出: "Hello, Alice!"

console.log(greet.myApply(null, ['Hi', '.'])); 
// 输出: "Hi, undefined." (非严格模式下指向 window,window.name 通常为空或特定值)

二、怎么优化 Webpack 打包?

Webpack 优化主要分为两个维度:构建速度优化 (开发体验)和 打包体积优化(用户体验)。结合 2026 年的技术背景,以下是核心策略:

1. 构建速度优化(让打包更快)
  • 开启持久化缓存 (Webpack 5+ 必配) :
    利用文件系统缓存,二次构建时复用未变动的模块,速度提升巨大。

    javascript 复制代码
    module.exports = {
      cache: {
        type: 'filesystem', // 使用文件系统缓存
        buildDependencies: { config: [__filename] } // 配置变更时缓存失效
      }
    };
  • 缩小构建范围 :

    • include / exclude :在 loader 中明确指定只处理 src 目录,排除 node_modules。
    • resolve.modules:指定模块搜索路径,减少递归查找。
    • resolve.extensions :减少后缀尝试次数,把常用的 .js, .jsx 放前面。
  • 多线程并行处理 :
    使用 thread-loader 将耗时的 loader(如 babel-loader, ts-loader)放入 worker 池中并行运行。

  • 减少插件使用 :
    生产环境才需要的插件(如压缩、提取 CSS)不要放在开发环境配置中。

2. 打包体积优化(让文件更小)
  • Tree Shaking (摇树优化) :

    • 确保代码使用 ES Module (import/export) 语法。
    • 在 package.json 中设置 "sideEffects": false 或配置具体文件,标记无副作用模块。
    • 生产模式默认开启,但需配合 usedExports: true。
  • 代码分割 (Code Splitting) :

    • 多入口分离 :配置多个 entry。
    • SplitChunksPlugin :提取公共代码(如 vendor 包),避免重复打包。
    • 动态导入 :使用 import() 语法实现路由级或组件级的懒加载。
    • optimization: { splitChunks: { chunks: 'all' } // 自动分割所有类型的 chunk }
  • 压缩与优化 :

    • JS/CSS 压缩 :Webpack 5 内置 TerserPlugin 和 CssMinimizerWebpackPlugin(需安装)。
    • 图片压缩 :使用 image-minimizer-webpack-plugin 或 squash-images-webpack-plugin。
    • Gzip/Brotli :使用 compression-webpack-plugin 生成 .gz 或 .br 文件,由 Nginx 直接serve。
  • 外部化依赖 (Externals) :
    将大型库(如 React, Vue, ECharts)通过 CDN 引入,不打包进 bundle.

    javascript 复制代码
    externals: {
      react: 'React',
      'react-dom': 'ReactDOM'
    }
  • 分析工具 :
    使用 webpack-bundle-analyzer 可视化分析包体积,精准定位大文件。


三、讲解下 Webpack 机制

Webpack 是一个静态模块打包工具 。它的核心机制可以概括为:"一切皆模块",从入口出发,递归解析依赖,最终生成一个或多个 Bundle。

1. 核心工作流程 (四大步骤)
  1. 初始化 (Initialization):

    • 读取配置文件 (webpack.config.js) 和 Shell 命令参数。
    • 实例化 Compiler 对象(负责整个构建过程的核心对象)。
    • 注册所有配置的插件 (plugins),监听生命周期钩子。
  2. 编译 (Compilation):

    • 从 entry 入口文件开始。
    • 调用配置的 Loader 对模块进行翻译(如 TS -> JS, SCSS -> CSS)。
    • 分析模块语法(AST),找出该模块依赖的其他模块(import, require)。
    • 递归地对每个依赖模块执行上述过程,直到所有依赖都被处理。
    • 最终形成一张完整的 依赖图 (Dependency Graph)。
  3. 输出 (Emission):

    • 根据依赖图和配置,将模块组合成一个或多个 Chunk。
    • 将 Chunk 转换成最终的 Bundle 文件(包含运行时代码和模块代码)。
    • 写入文件系统(磁盘)。
  4. 完成 (Done):

    • 触发完成钩子,通知插件构建结束。
2. 核心概念解析
  • Entry (入口):构建依赖图的起点。Webpack 从这里开始识别哪些模块应该被纳入。
  • Output (输出) :定义 Bundle 文件的输出路径和文件名(通常配合 [contenthash] 实现缓存优化)。
  • Loader (加载器) :
    • 作用:Webpack 原生只懂 JS 和 JSON。Loader 让它能处理其他类型的文件(CSS, Image, TS 等),将其转换为有效模块。
    • 机制 :链式执行,从右向左(或从下到上)。例如 style-loader(css-loader('a.scss'))。
  • Plugin (插件) :
    • 作用:扩展 Webpack 的功能,执行更广泛的任务(如打包优化、资源管理、环境变量注入)。
    • 机制 :基于 Tapable 库发布 - 订阅模式,在构建流程的特定生命周期钩子(Hook)中注入逻辑。
  • Mode (模式) :
    • development:优化构建速度,启用 NamedModulesPlugin。
    • production:优化输出体积,启用 Tree Shaking, Scope Hoisting, Uglify/Terser。
  • Chunk & Bundle :
    • Chunk:代码块,Webpack 内部编译过程中的中间产物。
    • Bundle:最终输出的文件,由一个或多个 Chunk 组成。
3. 运行机制图解(简化版)
javascript 复制代码
[Entry Files] 
    ↓ (读取)
[Loader 转换] (TS->JS, SCSS->CSS)
    ↓ (AST 分析依赖)
[Dependency Graph] (依赖图)
    ↓ (合并)
[Chunks] (代码块)
    ↓ (Plugin 处理/压缩)
[Bundles] (最终文件 -> dist/)
4. 为什么 Webpack 慢?

因为它是全量编译。每次修改代码,它都需要重新走一遍"读取->解析->转换->合并"的流程(虽然有了缓存和 HMR 优化,但原理上仍比 Vite 的 ESM 按需编译重)。这也是为什么现在流行 Vite(开发环境用 ESM 原生能力,生产环境用 Rollup)的原因。

相关推荐
破茧蝴蝶10 小时前
Python分布式爬虫完整教程
开发语言·python
狗凯之家源码网11 小时前
全新 PHP 轻量客服聊天室源码深度评测
开发语言·php·聊天室系统
远离UE411 小时前
UE5 Substrate Thin Film 源码拆析
开发语言·javascript·ue5
keyipatience11 小时前
JavaScript学习(1)书写位置,变量、数据类型、运算符
开发语言·前端·javascript·css·学习
栈帧之外12 小时前
【C++】STL之set
开发语言·c++
catchadmin13 小时前
免费可商用 PHP 管理后台 CatchAdmin V5.4.1 发布,新增 MCP 支持
开发语言·php
jimy114 小时前
c++的 Type Traits (二、更详细版本)
开发语言·c++
狗凯之家源码网14 小时前
纯 PHP+MySQL 应用市场系统源码实测!
开发语言·mysql·php
dishugj14 小时前
系统架构风险点、敏感点和权衡点的概念和区分
java·开发语言
geovindu15 小时前
rust:Memento Pattern(续)
开发语言·后端·设计模式·rust·行为模式·备忘录模