我很庆幸在回到 React 之前学到的 JavaScript 基础
Source: Dev.to
我的第一次(有趣的)JavaScript 误解 😅
当我第一次听说 JavaScript 时,我真的以为:
“Java 和 JavaScript 大概是同一种语言……只是在后面加个 script 而已。”
大错特错 😄。Java 和 JavaScript 完全是不同的语言,使用场景、语法以及背后的世界都不一样。摆脱这种误解后,我决定:
这一次,我不会急于求成。我会从最基础的地方开始。
JavaScript 中的一切都发生在执行上下文里 🧠
我学到的第一个(也是最重要的)概念是 执行上下文(Execution Context)。可以把它想象成一个封闭的容器,JavaScript 在其中运行你的代码。这个容器包含:
- 变量的信息
- 函数的信息
- 代码执行的顺序
每当 JavaScript 运行一个程序时,都会创建一个执行上下文。
执行上下文里有什么?
内存组件(变量环境)
- 存储变量和函数
- 以键‑值对的形式保存
- 变量最初的值为
undefined
代码组件(执行线程)
- 按行执行代码
- 严格遵循顺序
正因为如此,JavaScript 是:
- 同步的 → 一次执行一条指令
- 单线程的 → 按特定顺序执行代码
JavaScript 运行分为两个阶段 ⚙️
阶段 1:内存创建阶段
- 为所有变量和函数分配内存
- 变量得到
undefined - 函数完整地存入内存
阶段 2:代码执行阶段
- 逐行执行代码
- 实际的值被赋予
- 调用函数
用一个简单例子来理解 👇
var n = 2;
function square(num) {
var ans = num * num;
return ans;
}
var square2 = square(n);
var square4 = square(4);
🧠 内存创建阶段
JavaScript 首先会扫描整段代码并分配内存:
n→undefinedsquare→ 函数定义square2→undefinedsquare4→undefined
此时还没有执行任何代码。
▶️ 代码执行阶段
接下来 JavaScript 开始执行:
n被赋值为2- 函数
square暂时被跳过
当调用 square(n) 时:
- 创建一个新的执行上下文
- 为
num和ans分配内存 num = 2,ans = 4return ans将控制权返回
对 square(4) 也会重复相同的步骤。所有代码执行完毕后,全局执行上下文被销毁。
调用栈:幕后管理者 📚
JavaScript 使用 调用栈(Call Stack) 来跟踪所有执行上下文:
- 采用后进先出(LIFO)原则
- 当函数执行完毕,其对应的执行上下文会被移除
调用栈还有其他叫法:
- 执行上下文栈
- 程序栈
- 运行时栈
为什么这很重要(尤其对 React) 💡
当我终于弄清楚:
- 执行上下文
- 内存分配
- 调用栈
以下概念也逐渐变得清晰:
- 提升(Hoisting)
- 闭包(Closures)
useEffect- 状态更新
- React 中的意外行为
React 不再显得“神奇”——它变得合乎逻辑了。
最后感想 🙌
这一次,我没有急匆匆地冲进 React。我放慢脚步,尊重 JavaScript,学习它在幕后是如何运作的。
说实话,这让我成为了更好的 React 学习者。
如果你正准备开始学习 React,或是卡在某个地方:**不要跳过 JavaScript 基础。**它们不是可选的,而是根基。