欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > IT业 > 《JavaScript高级程序设计》——第四章:变量、作用域与内存管理

《JavaScript高级程序设计》——第四章:变量、作用域与内存管理

2025/2/25 10:14:14 来源:https://blog.csdn.net/weixin_62520914/article/details/145753752  浏览:    关键词:《JavaScript高级程序设计》——第四章:变量、作用域与内存管理

《JavaScript高级程序设计》——第四章:变量、作用域与内存管理

大家好!我是小哆啦,欢迎回到《JavaScript高级程序设计》的读书笔记大本营!在这章中,我们要聊的是两个让人头疼又迷人的话题——变量、作用域与内存管理。有些人一提到这些,就会感到一阵头晕目眩,恍若置身一场 JavaScript 版的迷宫大冒险!但今天,小哆啦会带你们轻松过关,深入了解这些概念,并且保持足够的幽默感,让你既能笑着学习,又能深入掌握其中的技术。

准备好了吗?系好你的安全带,让我们一起进入这场 JavaScript 的内存世界探险吧!


1. 基本类型与引用类型:内存里的“快餐”与“慢炖锅”

首先,我们得搞清楚 JavaScript 中最基本的类型——基本类型引用类型。在这两者之间,你就像是一个餐馆老板,一个快餐店(基本类型)和一个需要慢炖的菜系(引用类型),两者的运作方式完全不同。

基本类型:快餐小盘子,吃了就走

基本类型的数据存储在 栈内存 中,它们的特点是简单、高效,一旦离开作用域就会自动销毁,就像你吃完一份快餐,盘子一拿就消失,省时省力。

  • 值传递:你把基本类型的值传递给另一个变量,实际上是在复制一个副本,互不影响。
  • 内存释放:栈内存很神奇,一旦出了作用域,它会自动回收空间。
let a = 10;
let b = a;  // 这里 b 是 a 的副本
b = 20;
console.log(a);  // 10
console.log(b);  // 20

所以说,ab 是两个完全独立的小盘子,修改其中一个,不会影响另一个。

引用类型:慢炖锅,慢慢炖煮更美味

引用类型的数据存储在 堆内存 中,它们不像基本类型那么轻巧,它们需要更大的内存空间,也需要垃圾回收机制来清理。引用类型的变量存储的不是值,而是“指针”——指向堆内存中的一块地址,就像你点了一份大餐,把地址给了朋友,你俩一起吃这道菜。

  • 引用传递:当你传递一个对象时,传递的是指向对象的“指针”。
  • 内存管理:堆内存的管理比较麻烦,垃圾回收机制会定期清理不再被引用的内存。
let obj1 = { name: 'Dora' };
let obj2 = obj1;  // obj1 和 obj2 指向同一块内存
obj2.name = 'Nobita';
console.log(obj1.name);  // Nobita
console.log(obj2.name);  // Nobita

这里的 obj1obj2 就是“共享这顿大餐”的食客,修改其中一个,另一个也会发生变化。


2. 作用域与作用域链:变量的“探险之旅”

作用域是每个变量的家,而作用域链则是变量“探险”时的导航地图。在 JavaScript 中,作用域是 词法作用域,也就是说,变量的作用域在函数定义时就已经确定了,不是执行时才决定的。理解这一点对掌握 JavaScript 很重要。

作用域链:变量查找的“寻宝地图”

想象一下,变量查找就像是一次层层递进的寻宝之旅。每个作用域就像是一座山,而作用域链就像是通向宝藏的道路。当你在某个作用域中查找变量时,JavaScript 会从当前作用域开始,依次向上寻找,直到全局作用域。如果找不到,就表示没有这个变量,任务失败。

let globalVar = 'I am global!';
function outer() {let outerVar = 'I am outer!';function inner() {let innerVar = 'I am inner!';console.log(globalVar, outerVar, innerVar);  // 依次查找作用域链}inner();
}
outer();

在上面的例子中,inner 函数会从它自己的作用域开始找变量,如果找不到,就会去 outer 作用域,最后找到全局作用域。好像在玩一场“层层递进”的寻宝游戏。

闭包:作用域链的“长尾巴”

闭包就像是你带着一只“随身小背包”——即使外部函数已经执行完,闭包内的函数依然能记住外部函数的变量,就像带着过去的回忆一直在前进。闭包给了 JavaScript 更多的灵活性,但也可能带来内存泄漏的风险。

function outer() {let counter = 0;return function inner() {counter++;return counter;};
}
const increment = outer();
console.log(increment());  // 1
console.log(increment());  // 2

即便 outer 函数执行完毕,inner 函数依然可以访问 counter,因为它带着一个闭包。这就是闭包的“魔力”!


3. 内存管理:垃圾回收的隐形英雄

内存管理是 JavaScript 中最容易被忽视的部分,但它又至关重要。尤其是在大型应用中,垃圾回收器像一个隐形的清道夫,在你不经意的时候悄悄清理内存。

标记-清除:垃圾回收的“大扫除”

垃圾回收机制通常采用 标记-清除 算法,简单来说,就是垃圾回收器会标记所有被引用的对象,然后清除那些没有引用的“垃圾”对象。听起来很简单,但实际上,它需要不断“扫地”,避免内存泄漏。

内存泄漏:内存中的“定时炸弹”

内存泄漏就像是你家里多余的东西越堆越多,最后堆满了整个房间。典型的内存泄漏包括:

  • 未清除的事件监听器
  • 闭包未解除的引用
  • 循环引用,让垃圾回收器无法判断哪些对象不再需要。
function createLeak() {let obj = { name: 'leak' };obj = null;  // 这里应该解除对 obj 的引用,但因为闭包,obj 依然不会被回收
}
createLeak();

尽管你把 obj 设为 null,但是如果闭包持有了 obj 的引用,内存依然不会被回收,这就是内存泄漏的典型表现。


总结

第四章涉及了JavaScript中非常核心的概念,掌握了这些内容,可以帮助你写出更加高效、健壮的代码。在实际开发中,合理管理内存、作用域和闭包,不仅能提升代码的可维护性,还能有效避免常见的错误和性能问题。通过深入理解基本类型和引用类型的差异、作用域链的查找规则以及闭包的应用,你将能够处理更多复杂的场景,成为一名更强大的开发者。

好啦,今天的读书笔记就到这里!希望大家通过这些深入剖析,能在日常开发中游刃有余,代码写得更加得心应手。下次再见!

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词