前端技术栈全解 - JavaScript 核心篇——前端技术分享三

3 阅读7分钟

前端技术栈全解 - JavaScript 核心篇

本文为前端技术栈系列第一篇,完整覆盖 JavaScript 核心知识点,包含原理、用法、场景、替代方案、优劣势、优化方案、问题排查,可直接用于博客发布、学习笔记、面试复习。


目录

  1. JavaScript 基础语法与数据类型
  2. 函数(普通函数 / 箭头函数 / 闭包 / 高阶函数)
  3. 作用域与执行上下文
  4. 原型与原型链
  5. 异步编程(回调 / Promise/async-await)
  6. 事件循环(Event Loop)
  7. 数组常用方法与性能
  8. 深拷贝与浅拷贝
  9. 防抖与节流
  10. this 指向与绑定规则
  11. ES6+ 核心新特性
  12. JavaScript 内存管理与垃圾回收
  13. 常见报错与解决方案

1. JavaScript 基础语法与数据类型

核心定义

JavaScript 是一门弱类型、动态类型的解释型脚本语言,分为原始类型引用类型

分类

原始类型(7 种)

  • Undefined / Null / Boolean / Number / String / Symbol / BigInt
  • 存储方式:栈内存,值直接存储,赋值是值拷贝

引用类型

  • Object / Array / Function / Date
  • 存储方式:栈存地址,堆存数据,赋值是引用拷贝

用法

js

// 原始类型
let a = 10;
let b = a;
b = 20;
console.log(a); // 10(互不影响)

// 引用类型
let obj1 = { name: "js" };
let obj2 = obj1;
obj2.name = "ts";
console.log(obj1.name); // ts(指向同一内存)

使用场景

  • 页面交互逻辑
  • 数据处理与判断
  • 表单验证
  • DOM 操作
  • 异步请求处理

可替代方案

  • TypeScript(JS 超集,强类型)
  • Dart、Kotlin/JS(编译到 JS)

优劣势

优势

  • 无需编译,直接运行
  • 动态灵活,开发效率高
  • 全端可用(浏览器 / Node.js/ 小程序 / 桌面端)

劣势

  • 弱类型容易产生隐式转换错误
  • 运行时才能发现类型问题
  • 大型项目难以维护

优化方式

  • 使用 const > let > var
  • 避免隐式类型转换
  • 优先使用原始类型提升性能
  • 使用 TS 做类型约束

常见问题

问题 1:===== 区别?为什么用 ===

  • == 会进行隐式类型转换,容易出错
  • === 严格比较类型 + 值
  • 解决:永远优先使用 ===

问题 2:0.1 + 0.2 !== 0.3

  • 原因:JS 采用 IEEE 754 双精度浮点数,二进制无法精确表示部分小数
  • 解决:乘以 10 转整数计算后再除回

js

(0.1 * 10 + 0.2 * 10) / 10 === 0.3

2. 函数(普通 / 箭头 / 闭包 / 高阶)

原理

函数是一等公民,可以作为参数、返回值、变量赋值,本质是可调用的对象。

分类与用法

1)普通函数

js

function fn() {}
const fn = function() {}
  • 有自己的 this
  • arguments
  • 可以作为构造函数

2)箭头函数

js

const fn = () => {}
  • 无自己的 this,继承外层作用域
  • arguments
  • 不能用作构造函数
  • 不能使用 yield

3)闭包

js

function outer() {
  let a = 1;
  return function inner() {
    return a++;
  }
}
  • 原理:函数能够访问定义时的词法作用域,即使在外部执行
  • 场景:模块化、缓存、防抖节流

4)高阶函数

  • 接收函数为参数 或 返回函数
  • 例:map / filter / reduce

使用场景

  • 逻辑封装与复用
  • 模块化
  • 异步流程控制
  • 设计模式实现

可替代方案

无直接替代,函数是 JS 核心;可使用 Class 替代部分场景。

优劣势

优势

  • 灵活、可组合
  • 支持函数式编程
  • 闭包可实现私有变量

劣势

  • 闭包滥用会造成内存泄漏
  • 嵌套过深产生回调地狱
  • this 指向混乱

优化

  • 避免过度使用闭包
  • 箭头函数简化回调
  • 函数单一职责
  • 提取公共工具函数

常见问题

问题:闭包导致内存泄漏

  • 原因:闭包引用的变量无法被垃圾回收
  • 解决:手动解除引用 fn = null

3. 作用域与执行上下文

原理

  • 作用域:变量可访问范围
  • 执行上下文:函数运行时的环境(变量、this、作用域链)

分类

  • 全局作用域
  • 函数作用域
  • 块级作用域(let/const)

作用域链

内部作用域 -> 父级 -> ... -> 全局,逐级查找变量。

使用场景

  • 变量隔离
  • 避免全局污染
  • 模块化开发

优化

  • 减少全局变量
  • 使用块级作用域
  • 使用立即执行函数(IIFE)/ESModule

4. 原型与原型链

原理

JS 基于原型链实现继承,每个对象都有 __proto__ 指向构造函数的 prototype

核心公式

js

对象.__proto__ === 构造函数.prototype
构造函数.prototype.constructor === 构造函数

用法

js

function Person() {}
Person.prototype.say = () => console.log('hello')
const p = new Person()
p.say()

使用场景

  • 继承
  • 方法共享(节省内存)
  • 框架底层(Vue/React 源码大量使用)

可替代方案

  • ES6 class(语法糖,底层仍是原型)
  • 组合继承、寄生继承

优劣势

优势

  • 内存高效
  • 灵活的继承机制

劣势

  • 理解成本高
  • 继承关系不直观

常见问题

问题:instanceof 判断不准

  • 解决:使用 Object.prototype.toString.call(val)

5. 异步编程(回调 / Promise /async-await)

原理

JS 是单线程,异步用于不阻塞主线程处理耗时任务。

用法

1)回调函数

js

setTimeout(() => {}, 1000)
  • 问题:回调地狱

2)Promise

js

new Promise((resolve) => resolve())
.then()
.catch()

3)async-await(语法糖,基于 Promise)

js

async function fetchData() {
  const res = await axios.get('/api')
}

使用场景

  • 网络请求
  • 定时器
  • 文件操作
  • I/O 操作

可替代方案

  • Generator
  • RxJS(响应式编程)

优劣势

  • 回调:简单但难维护
  • Promise:解决地狱,链式优雅
  • async-await:最直观,同步写法

优化

  • 并行请求用 Promise.all
  • 避免滥用 await 造成串行

常见问题

问题:异步错误捕获

  • 解决:try/catch 包裹 await

6. 事件循环(Event Loop)

原理

JS 单线程 -> 任务队列 -> 事件循环调度宏任务 / 微任务

执行顺序

  1. 同步代码
  2. 微任务(Promise.then、queueMicrotask)
  3. 宏任务(setTimeout、setInterval、IO)

使用场景

  • 理解 JS 执行机制
  • 面试必考
  • 解决异步执行顺序问题

优化

  • 避免长任务阻塞渲染
  • 拆分大量计算为 chunk

7. 数组常用方法与性能

高频方法

  • forEach / map / filter / reduce / find / some / every
  • slice / splice / concat / flat

性能

  • 原生 for 循环 > forEach > map

优化

  • 避免频繁修改数组长度
  • 大数据量使用原生循环
  • 使用 Set 去重

8. 深拷贝与浅拷贝

浅拷贝

只拷贝第一层

  • Object.assign
  • 展开运算符 {...obj}

深拷贝

递归拷贝所有层级

js

JSON.parse(JSON.stringify(obj)) // 缺点:丢失函数、Date、RegExp、undefined

完美深拷贝:手写递归 + 类型判断

使用场景

  • 状态管理
  • 对象复制不污染原数据

9. 防抖与节流

防抖(debounce)

触发后 N 秒内只执行最后一次

  • 场景:搜索框输入、窗口 resize

节流(throttle)

N 秒内只执行一次

  • 场景:滚动、鼠标移动、高频点击

优化

  • 用于减少不必要请求与计算
  • 提升页面流畅度

10. this 指向

绑定规则

  1. 默认绑定:全局 /undefined(严格模式)
  2. 隐式绑定:对象调用
  3. 显式绑定:call /apply/bind
  4. new 绑定
  5. 箭头函数:继承外层 this

解决 this 混乱

  • 优先箭头函数
  • 使用 bind 固定 this

11. ES6+ 核心特性

  • let / const
  • 解构赋值
  • 展开 / 剩余运算符
  • Promise / async-await
  • 类 / 模块化
  • Map / Set

优势

代码更简洁、可读性更高、工程化更强


12. 内存管理与垃圾回收

垃圾回收机制

  • 标记清除
  • 引用计数

内存泄漏场景

  • 意外全局变量
  • 被遗忘的定时器
  • 闭包滥用
  • DOM 引用未清除

解决

  • 及时清除定时器
  • 解除事件监听
  • 闭包后手动置 null

13. 常见报错与解决方案

1. Cannot read property 'xxx' of undefined

  • 原因:访问了 undefined 上的属性
  • 解决:可选链 obj?.xxx

2. Maximum call stack size exceeded

  • 原因:递归死循环
  • 解决:加终止条件

3. Promise 未捕获异常

  • 解决:加 catch / 全局监听 unhandledrejection

4. 变量未定义

  • 解决:检查作用域 + 声明变量

总结

本文完整覆盖 JavaScript 核心知识点,从基础语法、函数、作用域、原型、异步、事件循环、性能优化、错误处理全维度详解,适合前端学习、面试、博客发布。

后续将更新:TypeScript、HTML/CSS、Vue、React、工程化、浏览器原理、网络请求、性能优化等全套前端技术栈文档。