乐趣区

关于前端:const关键字的秘密为什么它不总是像你想象的那样

本文首发于微信公众号:大迁世界, 我的微信:qq449245884,我会第一工夫和你分享前端行业趋势,学习路径等等。
更多开源作品请看 GitHub https://github.com/qq449245884/xiaozhi,蕴含一线大厂面试残缺考点、材料以及我的系列文章。

快来收费体验 ChatGpt plus 版本的,咱们出的钱
体验地址:https://chat.waixingyun.cn
能够退出网站底部技术群,一起找 bug.

该文章解说了 JavaScript 中 const 关键字的用法以及它的一些个性。该关键字用于创立常量,即一旦赋值之后就不能再批改。然而,应用 const 创立的对象和数组却能够被批改。本文通过解说“赋值”和“变异”之间的重要区别,具体解释了这一景象。

文章首先介绍了变量的三种申明形式:varletconst。它解释了这三种形式的区别,以及为什么应用 const 申明常量。而后,文章深入探讨了“赋值”和“变异”的区别,这是了解 const 的要害。尽管 const 创立的对象和数组。

注释开始

JavaScript 中的 const 关键字用于申明常量。常量通常被认为是“不能更改的变量”:

const hi = 5;
hi = 10;
// 🛑 Uncaught TypeError: Assignment to constant variable.
console.log(hi);
// -> 5

乏味的是,当我应用 const 创立一个对象时,我能够自在地更改它:

const person = {name: 'Hassan',};
person.name = 'Sujata';
// Seems to work?? 🤔
console.log(person);
// -> {name: 'Sujata'}

我怎么可能扭转 person 变量?我应用了 const

为了了解这个外表上的矛盾,咱们须要理解赋值和变异之间的区别。这是 JavaScript 中的外围概念,当您分明地了解这个区别时,许多事件就会变得更加清晰。

变量名作为标签

上面是齐全无效的 JavaScript 程序:

5;

这是另一个:

['apple', 'banana', 'cherry'];

在这两个例子中,我正在创立一些货色。一个数字和一个数组。当代码运行时,这些数据将被创立并存储在计算机的内存中。

这些程序并不是十分有用。我正在创立一些数据,但我没有拜访它的形式!

变量容许咱们在咱们创立的货色上贴上标签,以便当前能够援用它。

// Create it now...
const fruits = ['apple', 'banana', 'cherry'];

// ...and access it later:
console.log(fruits);
// -> ['apple', 'banana', 'cherry']

当我刚开始学习编程时,我认为代码是从左到右执行的:首先咱们创立一个 fruits 变量,就像一个空盒子,而后咱们在这个盒子里组装咱们的数组。

原来这并不是正确的心理模型。更精确的说法是,数组首先被创立,而后咱们将咱们的 fruits 标签指向它。

重新分配咱们的标签

当咱们应用 let 关键字创立一个变量时,咱们可能更改该标签所援用的“事物”。

例如,咱们能够将咱们的 fruits 标签指向一个新值:

这被称为重新分配。实际上,fruits 标签应该指向一个齐全不同的值:

// We start with a labeled array:
  let fruits = ['apple', 'banana', 'cherry'];

// ⚠️⚠️⚠️⚠️
// 从下面的列表中抉择其余选项
// 查看它如何在代码中翻译!

咱们没有批改数据,咱们批改的是标签。咱们将其从原始数组中分离出来,连贯到一个新数组中。

相比之下,应用 const 创立的变量无奈从新赋值:

这是 letconst 之间的基本区别。当咱们应用 const 时,咱们创立了一个不可捣毁的链接,将变量名和一段数据分割在一起。

然而,问题在于:咱们依然能够批改数据自身!只有标签放弃完整无缺。

例如,应用数组,咱们能够轻松地增加 / 删除其中的我的项目。fruits 变量依然连贯到同一个数组:

这被称为 变异(mutation)。咱们通过增加 / 删除我的项目来编辑数组的值。

这是另一个例子,应用对象而不是数组。只有标签持续指向雷同的对象,咱们就能够编辑对象中的键 / 值。

重新分配(将变量名称指向新事物)和突 mutation(编辑事物内的数据)之间存在基本区别。

当咱们应用 const 创立一个常量时,咱们能够百分之百地确定该变量永远不会被重新分配,然而在变异方面没有任何承诺。const 并不齐全阻止变异。

这里还有一个问题:像字符串和数字这样的“原始”数据类型是不可变的。这使得事件变得更加凌乱。咱们将在下一节中探讨。

如果你正在寻找一种办法来确保你的数据不会被批改,那么有一个办法叫做 Object.freeze(),它能够派上用场。应用该办法能够将对象和数组解冻,使它们变成只读的,这样就能够爱护它们免受批改。这是一种十分有用的办法,特地是在须要确保数据的不可变性时。应用这种办法,即便应用const 关键字也能够确保你的数据不会被批改

// With arrays:
const arr = Object.freeze([1, 2, 3]);
arr.push(4);
console.log(arr);
// -> [1, 2, 3]


// With objects:
const person = Object.freeze({name: 'Hassan'});
person.name = 'Sujata';
console.log(person);
// -> {name: 'Hassan'}

据我所知,Object.freeze()是防弹的。无奈批改应用此办法解冻的对象 / 数组。

同样,如果你应用 TypeScript,你也能够应用 as const 断言来实现相似的后果

const arr = [1, 2, 3] as const;
arr.push(4);
// 🛑 Error: Property 'push' does not exist
//           on type 'readonly [1, 2, 3]'.

与所有动态类型一样,当代码被编译为 JavaScript 时,这些爱护就会隐没,因而这并不能提供与 Object.freeze()雷同数量的爱护。

原始数据类型

到目前为止,咱们看到的所有示例都波及对象和数组。然而如果咱们有一个“原始”数据类型,例如字符串、数字或布尔值,该怎么办呢?

以一个数字为例:

let age = 36;
age = 37;

咱们应该如何解释这个?咱们是将 age 标签重新分配给一个新值,还是渐变这个数字,将 36 编辑为 37

这就是问题所在:JavaScript 中的所有原始数据类型都是不可变的。无奈“编辑”数字的值。咱们只能将变量重新分配给不同的值。

伪装有一个蕴含所有可能数字的大列表。咱们曾经将 age 变量调配给数字36,但咱们能够将它指向列表中的任何其余数字:

要明确的是,浏览器并没有所有可能数字的大索引。我心愿在这里论述的重点是数字自身无奈更改。咱们只能更改标签指向的数字。

这实用于所有原始值类型,包含字符串、布尔值、null 等。

如上所述,在 JavaScript 中,原始值是不可变的; 它们不能被编辑。但如果他们能做到呢? 如果数字自身能够扭转,那么语法会是什么样子呢? 它看起来是这样的:

// 编辑数字 36 的值
36 = 37;

// 36 这个数字不再存在了
console.log(36); // 37

所以,如果咱们能够在 JavaScript 中扭转原始值,那就意味着基本上笼罩某些数字,这样它们就永远不会再被援用了! 这显然会让人感到困惑和无助,这就是为什么在 JavaScript 中根本类是不可变的。

编辑中可能存在的 bug 没法实时晓得,预先为了解决这些 bug, 花了大量的工夫进行 log 调试,这边顺便给大家举荐一个好用的 BUG 监控工具 Fundebug。

交换

有幻想,有干货,微信搜寻 【大迁世界】 关注这个在凌晨还在刷碗的刷碗智。

本文 GitHub https://github.com/qq449245884/xiaozhi 已收录,有一线大厂面试残缺考点、材料以及我的系列文章。

退出移动版