《JS 从入门到进阶:揭开 ES6 let与const及内存管理的神秘面纱》😎

205 阅读5分钟

前言

JavaScript 作为前端开发的灵魂语言,一直在不断地进化和革新。ES6 的诞生,为 JavaScript 注入了新的活力,带来了诸如 let 和 const 等强大特性。今天,我们就通过几个实际的代码例子,深入浅出地探索 ES6 特性以及 JavaScript 中的内存管理机制。🤓

一、走进 ES6:let 和 const 的奇妙世界

1.1 let 与块级作用域的魔法

先看下面这段 HTML 文件中的 JavaScript 代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        // 循环
        // 块级作用域
        for (let i = 0; i < 10; i++) {
            setTimeout(() => {
                console.log(i);
            }, 1000);
        }
    </script>
</body>
</html>

在这个例子中,我们使用 let 声明变量 ilet 具有块级作用域,这意味着 i 只在 for 循环的块内部有效。setTimeout 是一个异步函数,当它执行时,for 循环早已结束。但由于 let 的块级作用域特性,每个 setTimeout 回调函数都拥有自己独立的 i 值,所以最终会依次输出 0 到 9。想象一下,这就像是给每个回调函数都分配了一个专属的小盒子,里面装着属于它自己的 i 值。😜

1.2 const 的独特魅力

再看另一个 HTML 文件中的代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>朋友们</title>
</head>
<body>
<script>
const age = 18;
const friends = [
    {
        name:'小吴',
        hometown:'上饶',
        collage:'湖南工业大学',
    },
    {
        name:'小谢',
        hometown:'赣州',
        collage:'东华理工大学',
    },
];
friends.push({
    name:'小王',
    hometown:'宜春',
})
const newFriends = friends;
newFriends.push({
    name:'小宋',
    hometown:'宜春',
})
// 栈 队列
newFriends.unshift({
    name:'小美',
    hometown:'九江',
});
</script>
</body>
</html>

这里我们使用 const 声明常量。对于 const 来说,简单数据类型一旦赋值就不能再改变,而对于复杂数据类型(如对象和数组),它保证的是变量指向的内存地址不变,但对象或数组的内容是可以修改的。就好比我们给一个房子贴上了标签(常量),房子的地址不能变,但房子里面的家具(内容)是可以随意更换的。所以在这段代码中,我们可以对 friends 数组进行 push 和 unshift 操作。😏

二、const 的内存管理秘籍

2.1 简单与复杂数据类型的内存差异

在 JavaScript 里,数据类型分为简单数据类型(像 numberstringboolean 等)和复杂数据类型(如 objectarray 等)。const 对这两种类型的处理方式大不相同。
对于简单数据类型,const 声明的常量值无法改变。例如:

const num = 10;
// num = 20;  // 这会报错,因为 num 是常量,不能重新赋值

而对于复杂数据类型,const 声明的常量指向的内存地址不能改变,但对象或数组的内容可以改变。例如:

const obj = { name: '小王' };
obj.name = '小明';  // 这是允许的,因为只是修改了对象的属性
// obj = { name: '小白' };  // 这会报错,因为尝试改变 obj 指向的内存地址

2.2 赋值规则:值传递与引用式赋值

简单数据类型在赋值时是值传递,也就是把值复制一份给新的变量。比如:

let a = 10;
let b = a;
b = 20;
console.log(a);  // 输出 10,a 的值不受 b 的影响

这就好像我们把一个苹果复制了一份给另一个人,两个人的苹果是相互独立的。🍎
复杂数据类型在赋值时是引用式赋值,即把对象或数组的内存地址复制给新的变量。例如:

const arr1 = [1, 2, 3];
const arr2 = arr1;
arr2.push(4);
console.log(arr1);  // 输出 [1, 2, 3, 4],因为 arr1 和 arr2 指向同一个内存地址

这就好比两个人共享同一间房子,一个人对房子做了改变,另一个人也能看到变化。🏠

三、ES6 特性:革新 JavaScript 的力量

3.1 弥补 ES5 的短板

ES6 的 let 和 const 很好地弥补了 ES5 只有 var 的不足。var 没有块级作用域,还会发生变量提升,这常常会让代码的阅读和执行产生歧义。例如:

console.log(x);  // 输出 undefined,因为 var 会发生变量提升
var x = 10;

而 let 和 const 不会发生变量提升,并且具有块级作用域,大大提高了代码的可读性和可维护性。👏

3.2 适应大型应用开发的潮流

早期的 JavaScript 主要用于页面交互,功能相对简单。但随着互联网的发展,需要 JavaScript 成为企业级大型应用开发的语言。ES6 的出现,让 JavaScript 更具竞争力,吸引了更多开发者。就像一辆旧车经过改装,变得更加适应长途旅行。🚗

3.3 杜绝全局变量污染

在 ES5 中,使用 var 声明的变量会挂在 window 对象上,从而污染全局变量。而 let 和 const 不会出现这种情况,避免了不合理的全局变量污染。这就好比我们把垃圾都放在该放的地方,让整个环境更加整洁。🚮

四、总结

通过以上的代码示例和分析,我们深入了解了 ES6 中的 let 和 const 特性,以及 JavaScript 中的内存管理机制。let 和 const 的出现,让 JavaScript 更加完善和强大,能够更好地应对现代前端开发的挑战。在实际开发中,我们要合理运用 let 和 const,摒弃 var 的使用,从而提高代码的质量和可维护性。希望大家在今后的 JavaScript 之旅中,能够熟练运用这些特性,创造出更加优秀的代码!🎉