Skip to content

快速夯实 JavaScrilpt 基础的 33 个概念 #444

Description

@mqyqingfeng

你好,我是冴羽

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

很多人以为这很简单,但其实坑很多:

typeof null // "object" ❌ 这是 JS 的历史 bug
typeof NaN  // "number" ✅ NaN 确实是数字类型

原始类型是不可变的。 当你“修改”一个字符串时,其实是创建了新字符串:

let str = "hello";
str[0] = "H"; // 无效,原始类型不可变
str = "Hello"; // 这是重新赋值,不是修改

1.2. 原始类型 vs 对象 (Primitives vs Objects)

这是 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 的隐式类型转换是最让人头疼的特性之一。

[] == ![]   // true ❓
[] + []     // ""
[] + {}     // "[object Object]"
{} + []     // 0

为什么 [] == ![] 是 true?

  1. ![] 先转成 boolean,空数组是真值,取反得 false

  2. [] == false 触发类型转换

  3. [] 转成字符串 ""

  4. "" 转成数字 0

  5. false 转成数字 0

  6. 0 == 0true

所以永远用 === 而不是 ==,除非你真的知道自己在干什么。

1.4. 相等性比较 (Equality: == vs ===)

  • == 会进行类型转换后比较

  • === 严格比较,类型不同直接返回 false

  • Object.is() 更严格,能正确处理 NaN+0/-0

NaN === NaN           // false
Object.is(NaN, NaN)   // true

+0 === -0             // true
Object.is(+0, -0)     // false

2. 作用域与执行机制:JavaScript 的运行时

2.1. 调用栈 (Call Stack)

JavaScript 是单线程的,所有函数调用都在一个调用栈里按 LIFO (后进先出) 执行。

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 最强大也最容易出问题的特性:函数可以访问其定义时的外部变量,即使外部函数已经执行完毕。

function createCounter() {
  let count = 0;
  return function() {
    return ++count;
  };
}

const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2

闭包的坑:如果不小心,会导致内存泄漏。

// ❌ 内存泄漏示例
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 条绑定规则:

  1. 默认绑定this 指向全局对象 (严格模式下是 undefined)

  2. 隐式绑定:作为对象方法调用,this 指向该对象

  3. 显式绑定:用 call/apply/bind 指定 this

  4. new 绑定new 创建新对象,this 指向新对象

  5. 箭头函数:没有自己的 this,继承外层 this

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]] 链接,指向它的原型对象。

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 语法只是原型继承的语法糖:

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,还可以用工厂函数创建对象:

// 工厂函数
function createPerson(name) {
  return {
    name,
    sayHi() {
      console.log("Hi, " + this.name);
    }
  };
}

const p = createPerson("冴羽");

工厂函数更灵活,不需要 new,也不用担心 this 丢失。

4. 函数式编程:JavaScript 的另一面

4.1. 高阶函数 (Higher-Order Functions)

高阶函数 是接收函数作为参数,或返回函数的函数。

// 接收函数作为参数
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

这是函数式编程的三大金刚:

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

链式调用更优雅:

numbers
  .filter(x => x > 2)
  .map(x => x * 2)
  .reduce((sum, x) => sum + x, 0); // 24

4.3. 纯函数 (Pure Functions)

纯函数 有两个特征:

  1. 相同输入永远返回相同输出

  2. 没有副作用 (不修改外部状态)

// ✅ 纯函数
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)

柯里化 是把多参数函数转成单参数函数链:

// 普通函数
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

函数组合 是把多个函数组合成一个:

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)

递归是函数调用自己。经典的阶乘:

function factorial(n) {
  if (n <= 1) return 1; // 基础情况
  return n * factorial(n - 1); // 递归调用
}

factorial(5); // 120

递归的坑:容易栈溢出。 可以用尾递归优化或改成循环。

5. 异步编程:JavaScript 的精髓

5.1. 回调函数 (Callbacks)

最早的异步方案,但容易陷入 回调地狱

getData(function(a) {
  getMoreData(a, function(b) {
    getMoreData(b, function(c) {
      getMoreData(c, function(d) {
        // 回调地狱 🔥
      });
    });
  });
});

5.2. Promise

Promise 解决了回调地狱,让异步代码更优雅:

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 的语法糖,让异步代码看起来像同步:

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:

const [user, posts] = await Promise.all([
  fetchUser(),
  fetchPosts()
]);

5.4. Event Loop (事件循环)

这是 JavaScript 异步的核心机制。

JavaScript 是单线程的,但通过 Event Loop 实现了异步:

  1. 调用栈 执行同步代码

  2. 异步任务放入 任务队列

  3. 调用栈清空后,Event Loop 从队列取任务执行

微任务 (Microtask) 优先级高于宏任务 (Macrotask):

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)

生成器函数可以暂停和恢复执行:

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)

// 选择元素
const el = document.querySelector(".class");

// 修改内容
el.textContent = "新内容";

// 添加事件
el.addEventListener("click", () => {
  console.log("clicked");
});

性能优化:批量 DOM 操作用 DocumentFragment,避免频繁重排重绘。

6.2. HTTP & Fetch API

// 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 可以多线程运行:

// 主线程
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

// 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 避免全局污染:

(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)

const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
emailRegex.test("hello@example.com"); // true

8.2. 错误处理 (Error Handling)

try {
  riskyOperation();
} catch (err) {
  console.error("Error:", err.message);
} finally {
  cleanup(); // 无论如何都会执行
}

8.3. 数据结构 (Data Structures)

JavaScript 内置:Array、Object、Map、Set、WeakMap、WeakSet

// 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 实战指南》。

欢迎围观我的“网页版朋友圈”,关注我的公众号:冴羽(或搜索 yayujs),每天分享前端知识、AI 编程干货。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions