你好,我是冴羽。
AI 时代,很多同学很迷茫。 既想夯实基础,又要跟进 AI,于是学这学那,沉不下心来,结果三天打鱼两天晒网。
最近我系统梳理了一遍 33 JavaScript Concepts 这个项目,它把 JavaScript 最核心的 33 个概念整理成了一个完整的知识体系。
我发现:这 33 个概念,恰好覆盖了从语言基础到工程实践的完整链路。正是你快速夯实 JavaScrilpt 基础的路径。
今天我就按照学习难度和逻辑关系,把这 33 个概念重新分类整理,帮你建立一个完整的 JavaScript 知识框架。
1. 类型系统:JavaScript 的地基
1.1. 原始类型 (Primitive Types)
JavaScript 有 7 种原始类型:string、number、bigint、boolean、undefined、null、symbol。
很多人以为这很简单,但其实坑很多:
javascript
typeof null // "object" ❌ 这是 JS 的历史 bug
typeof NaN // "number" ✅ NaN 确实是数字类型
原始类型是不可变的。 当你"修改"一个字符串时,其实是创建了新字符串:
javascript
let str = "hello";
str[0] = "H"; // 无效,原始类型不可变
str = "Hello"; // 这是重新赋值,不是修改
1.2. 原始类型 vs 对象 (Primitives vs Objects)
这是 JavaScript 最核心的区别:原始类型按值传递,对象按引用传递。
javascript
// 原始类型:复制值
let a = 1;
let b = a;
b = 2;
console.log(a); // 1,a 不受影响
// 对象:复制引用
let obj1 = { x: 1 };
let obj2 = obj1;
obj2.x = 2;
console.log(obj1.x); // 2,obj1 也变了!
这直接影响了函数参数传递、性能优化、React 的 immutable 更新等一系列问题。
1.3. 类型强制转换 (Type Coercion)
JavaScript 的隐式类型转换是最让人头疼的特性之一。
javascript
[] == ![] // true ❓
[] + [] // ""
[] + {} // "[object Object]"
{} + [] // 0
为什么 [] == ![] 是 true?
-
![]先转成 boolean,空数组是真值,取反得false -
[] == false触发类型转换 -
[]转成字符串"" -
""转成数字0 -
false转成数字0 -
0 == 0为true
所以永远用 === 而不是 ==,除非你真的知道自己在干什么。
1.4. 相等性比较 (Equality: == vs ===)
-
==会进行类型转换后比较 -
===严格比较,类型不同直接返回 false -
Object.is()更严格,能正确处理NaN和+0/-0
javascript
NaN === NaN // false
Object.is(NaN, NaN) // true
+0 === -0 // true
Object.is(+0, -0) // false
2. 作用域与执行机制:JavaScript 的运行时
2.1. 调用栈 (Call Stack)
JavaScript 是单线程的,所有函数调用都在一个调用栈里按 LIFO (后进先出) 执行。
javascript
function first() {
second();
console.log("first");
}
function second() {
console.log("second");
}
first();
// 输出:
// "second"
// "first"
栈溢出 (Stack Overflow) 就是调用栈爆了,通常是递归没写好。
2.2. 作用域与闭包 (Scope & Closures)
JavaScript 有 3 种作用域:全局作用域、函数作用域、块级作用域 (let/const)。
闭包 是 JavaScript 最强大也最容易出问题的特性:函数可以访问其定义时的外部变量,即使外部函数已经执行完毕。
javascript
function createCounter() {
let count = 0;
return function() {
return ++count;
};
}
const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
闭包的坑:如果不小心,会导致内存泄漏。
javascript
// ❌ 内存泄漏示例
function attachHandler() {
const bigData = new Array(1000000).fill("data");
document.getElementById("btn").onclick = function() {
console.log(bigData.length); // 闭包持有 bigData
};
}
2.3. this, call, apply & bind
this 是 JavaScript 最让人困惑的关键字。它的值不是在定义时确定的,而是在调用时确定的。
5 条绑定规则:
-
默认绑定 :
this指向全局对象 (严格模式下是undefined) -
隐式绑定 :作为对象方法调用,
this指向该对象 -
显式绑定 :用
call/apply/bind指定this -
new 绑定 :
new创建新对象,this指向新对象 -
箭头函数 :没有自己的
this,继承外层this
javascript
const obj = {
name: "obj",
getName: function() {
return this.name;
},
getNameArrow: () => {
return this.name; // 箭头函数的 this 指向外层
}
};
obj.getName(); // "obj"
obj.getNameArrow(); // undefined (外层是全局)
const fn = obj.getName;
fn(); // undefined (丢失了 this)
fn.call(obj); // "obj" (显式绑定)
3. 面向对象:原型链与继承
3.1. 原型与对象创建 (Prototypes & Object Creation)
JavaScript 不是传统的类继承,而是 原型继承 。每个对象都有一个隐藏的 [[Prototype]] 链接,指向它的原型对象。
javascript
function Person(name) {
this.name = name;
}
Person.prototype.sayHi = function() {
console.log("Hi, " + this.name);
};
const p = new Person("冴羽");
p.sayHi(); // "Hi, 冴羽"
当你访问 p.sayHi 时,JavaScript 会先在 p 自身找,找不到就去 Person.prototype 找,这就是原型链。
3.2. 继承与多态 (Inheritance & Polymorphism)
ES6 的 class 语法只是原型继承的语法糖:
javascript
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(this.name + " makes a sound");
}
}
class Dog extends Animal {
speak() {
console.log(this.name + " barks");
}
}
const dog = new Dog("旺财");
dog.speak(); // "旺财 barks" (多态:子类覆盖父类方法)
3.3. 工厂函数与类 (Factories & Classes)
除了 class,还可以用工厂函数创建对象:
javascript
// 工厂函数
function createPerson(name) {
return {
name,
sayHi() {
console.log("Hi, " + this.name);
}
};
}
const p = createPerson("冴羽");
工厂函数更灵活,不需要 new ,也不用担心 this 丢失。
4. 函数式编程:JavaScript 的另一面
4.1. 高阶函数 (Higher-Order Functions)
高阶函数 是接收函数作为参数,或返回函数的函数。
javascript
// 接收函数作为参数
function repeat(n, action) {
for (let i = 0; i < n; i++) {
action(i);
}
}
repeat(3, console.log); // 0 1 2
// 返回函数
function multiplier(factor) {
return number => number * factor;
}
const double = multiplier(2);
console.log(double(5)); // 10
4.2. map, reduce, filter
这是函数式编程的三大金刚:
javascript
const numbers = [1, 2, 3, 4, 5];
// map:转换每个元素
numbers.map(x => x * 2); // [2, 4, 6, 8, 10]
// filter:筛选元素
numbers.filter(x => x > 2); // [3, 4, 5]
// reduce:累积计算
numbers.reduce((sum, x) => sum + x, 0); // 15
链式调用更优雅:
javascript
numbers
.filter(x => x > 2)
.map(x => x * 2)
.reduce((sum, x) => sum + x, 0); // 24
4.3. 纯函数 (Pure Functions)
纯函数 有两个特征:
-
相同输入永远返回相同输出
-
没有副作用 (不修改外部状态)
javascript
// ✅ 纯函数
function add(a, b) {
return a + b;
}
// ❌ 不纯:依赖外部变量
let count = 0;
function increment() {
return ++count;
}
// ❌ 不纯:修改了参数
function addToArray(arr, item) {
arr.push(item); // 副作用!
return arr;
}
纯函数更容易测试、调试和优化。React 的函数组件就应该是纯函数。
4.4. 柯里化与函数组合 (Currying & Composition)
柯里化 是把多参数函数转成单参数函数链:
javascript
// 普通函数
function add(a, b, c) {
return a + b + c;
}
// 柯里化
function curriedAdd(a) {
return function(b) {
return function(c) {
return a + b + c;
};
};
}
curriedAdd(1)(2)(3); // 6
函数组合 是把多个函数组合成一个:
javascript
const compose = (f, g) => x => f(g(x));
const double = x => x * 2;
const square = x => x * x;
const doubleThenSquare = compose(square, double);
doubleThenSquare(3); // (3 * 2)² = 36
4.5. 递归 (Recursion)
递归是函数调用自己。经典的阶乘:
javascript
function factorial(n) {
if (n <= 1) return 1; // 基础情况
return n * factorial(n - 1); // 递归调用
}
factorial(5); // 120
递归的坑:容易栈溢出。 可以用尾递归优化或改成循环。
5. 异步编程:JavaScript 的精髓
5.1. 回调函数 (Callbacks)
最早的异步方案,但容易陷入 回调地狱:
javascript
getData(function(a) {
getMoreData(a, function(b) {
getMoreData(b, function(c) {
getMoreData(c, function(d) {
// 回调地狱 🔥
});
});
});
});
5.2. Promise
Promise 解决了回调地狱,让异步代码更优雅:
javascript
getData()
.then(a => getMoreData(a))
.then(b => getMoreData(b))
.then(c => getMoreData(c))
.catch(err => console.error(err));
Promise 有 3 种状态:pending、fulfilled、rejected。状态一旦改变就不可逆。
5.3. async/await
async/await 是 Promise 的语法糖,让异步代码看起来像同步:
javascript
async function fetchData() {
try {
const a = await getData();
const b = await getMoreData(a);
const c = await getMoreData(b);
return c;
} catch (err) {
console.error(err);
}
}
并行执行用 Promise.all:
javascript
const [user, posts] = await Promise.all([
fetchUser(),
fetchPosts()
]);
5.4. Event Loop (事件循环)
这是 JavaScript 异步的核心机制。
JavaScript 是单线程的,但通过 Event Loop 实现了异步:
-
调用栈 执行同步代码
-
异步任务放入 任务队列
-
调用栈清空后,Event Loop 从队列取任务执行
微任务 (Microtask) 优先级高于宏任务 (Macrotask):
javascript
console.log("1");
setTimeout(() => console.log("2"), 0); // 宏任务
Promise.resolve().then(() => console.log("3")); // 微任务
console.log("4");
// 输出:1 4 3 2
为什么?因为 Promise 的 .then 是微任务,在当前宏任务结束后立即执行,而 setTimeout 是宏任务,要等下一轮。
5.5. 生成器与迭代器 (Generators & Iterators)
生成器函数可以暂停和恢复执行:
javascript
function* idGenerator() {
let id = 1;
while (true) {
yield id++;
}
}
const gen = idGenerator();
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
生成器可以实现惰性求值、无限序列等高级特性。
6. 浏览器与 Web API
6.1. DOM 操作 (DOM Manipulation)
javascript
// 选择元素
const el = document.querySelector(".class");
// 修改内容
el.textContent = "新内容";
// 添加事件
el.addEventListener("click", () => {
console.log("clicked");
});
性能优化:批量 DOM 操作用 DocumentFragment,避免频繁重排重绘。
6.2. HTTP & Fetch API
javascript
// GET 请求
const response = await fetch("https://api.example.com/data");
const data = await response.json();
// POST 请求
await fetch("https://api.example.com/data", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ name: "冴羽" })
});
6.3. Web Workers
Web Workers 让 JavaScript 可以多线程运行:
javascript
// 主线程
const worker = new Worker("worker.js");
worker.postMessage({ data: "heavy computation" });
worker.onmessage = (e) => {
console.log("Result:", e.data);
};
// worker.js
self.onmessage = (e) => {
const result = heavyComputation(e.data);
self.postMessage(result);
};
适合 CPU 密集型任务,不会阻塞主线程。
7. 模块化与现代语法
7.1. ES Modules
javascript
// math.js
export function add(a, b) {
return a + b;
}
export default function multiply(a, b) {
return a * b;
}
// main.js
import multiply, { add } from "./math.js";
ES Modules 是静态的,支持 Tree Shaking,能减小打包体积。
7.2. IIFE & Namespaces
在模块化之前,用 IIFE 避免全局污染:
javascript
(function() {
const privateVar = "私有变量";
window.MyModule = {
publicMethod() {
console.log(privateVar);
}
};
})();
7.3. Modern JS Syntax (ES6+)
-
解构赋值 :
const { name, age } = user; -
展开运算符 :
const newArr = [...arr, 4, 5]; -
箭头函数 :
const add = (a, b) => a + b; -
模板字符串 :
const msg = `Hello, ${name}`; -
可选链 :
user?.address?.city -
空值合并 :
const value = input ?? "default";
8. 工程化与最佳实践
8.1. 正则表达式 (Regular Expressions)
javascript
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
emailRegex.test("hello@example.com"); // true
8.2. 错误处理 (Error Handling)
javascript
try {
riskyOperation();
} catch (err) {
console.error("Error:", err.message);
} finally {
cleanup(); // 无论如何都会执行
}
8.3. 数据结构 (Data Structures)
JavaScript 内置:Array、Object、Map、Set、WeakMap、WeakSet。
javascript
// Map:键可以是任意类型
const map = new Map();
map.set({ id: 1 }, "value");
// Set:自动去重
const set = new Set([1, 2, 2, 3]); // Set {1, 2, 3}
8.4. 算法与 Big O (Algorithms & Big O)
时间复杂度:
-
O(1) :常数时间,如数组访问
arr[0] -
O(n):线性时间,如数组遍历
-
O(n²):平方时间,如双层循环
-
O(log n):对数时间,如二分查找
写代码前先想复杂度,避免性能灾难。
8.5. 设计模式 (Design Patterns)
常用模式:
-
单例模式:全局只有一个实例
-
工厂模式:用函数创建对象
-
观察者模式:发布-订阅,如 EventEmitter
-
代理模式:拦截对象操作,如 Vue 3 的响应式
8.6. 整洁代码 (Clean Code)
-
有意义的命名
-
函数只做一件事
-
避免深层嵌套
-
DRY (Don't Repeat Yourself)
8.7. JavaScript 引擎 (JavaScript Engines)
V8 引擎的优化:
-
JIT 编译:热代码编译成机器码
-
隐藏类:对象结构相同时共享类
-
内联缓存:缓存属性访问路径
写"引擎友好"的代码:保持对象结构稳定、避免动态添加属性。
总结
这 33 个概念构成了 JavaScript 的完整知识体系:
-
类型系统 是地基,理解值和引用的区别
-
作用域与执行机制 是运行时,掌握闭包和 this
-
面向对象 是原型链,理解继承本质
-
函数式编程 是另一面,写出优雅的代码
-
异步编程 是精髓,Event Loop 是核心
-
浏览器与 Web API 是实战,DOM 和 Fetch 是基础
-
模块化与现代语法 是趋势,ES6+ 是标配
-
工程化与最佳实践 是进阶,设计模式和性能优化是分水岭
如果你能把这 33 个概念都吃透,你就真的懂 JavaScript 了。
不是说你要把每个概念都研究到底层实现,而是:知道它们是什么、为什么需要它们、什么时候用、怎么用、有什么坑。
JavaScript 看起来简单,但要写好很难。这 33 个概念,就是从"会写"到"写好"的必经之路。
我是冴羽,10 年笔耕不辍,专注前端领域,更新了 10+ 系列、300+ 篇原创技术文章,翻译过 Svelte、Solid.js、TypeScript 文档,著有小册《Next.js 开发指南》、《Svelte 开发指南》、《Astro 实战指南》。
欢迎围观我的"网页版朋友圈",每天分享前端知识、AI 编程干货。