附上为何铁人赛文章会出现在这里的说明:2022 铁人赛|Day1 报名失败,还是要开赛吧!
背景脉络
不知道大家有没有产生过这样的疑问..
const person = { bodyHeight: 180, favColor: 'black'};person.favColor = 'blue';console.log(person); // print: {bodyHeight: 180, favColor: 'blue'}
。 为什么里面的值变了?
。 不是用 const
了吗?
。 说好的宣告后不可更改的特性失灵了吗?
今天学到的内容刚好替我解决的这样的疑惑,原来跟 Data types 有关!以下整理~~
主题笔记
一、Data Types 分两类
根据储存位置不同,可以分成 Primitive Types & Reference Types(或者可以说 Primitives & Objects)
Primitive Types 的值储存在 Call Stack,而 Reference Types 的值储存在 Heap
⬆️ 图片来自于Jonas Schmedtmann的课程讲义
二、Data Types 储存方式
⬆️ 图片来自于Jonas Schmedtmann的课程讲义,下面解说(打完发现好长呀!希望有表达清楚)
.
Primitive Types
age = 30
,JS engine 会在 Call Stack 上创造一个 age identifierage identifier 指向存着「30」的「Stack memory address」接着宣告oldAge = age
,JS engine 会在 Call Stack 上创造 oldAge identifieroldAge identifier 指向与 age identifier 同一个 「Stack memory address」接着重新为 age 赋值age = 31
,已存在的 age identifier 会重新指向存着「31」的「Stack memory address」所以 log 时,age
与oldAge
都有它们各自指向的值.
Reference Types
宣告me = {...}
,JS engine 会在 Heap 创造出存着「物件值」的「Heap memory address」然后 Call Stack 上会创造 me identifierme identifier 指向存着「Heap memory address值」的「Stack memory address」而这个「Heap memory address值」会指向 Heap 中的 「Heap memory address」,进而对应到「物件值」接着宣告friend = me
,Call Stack 上会创造 friend identifierfriend identifier 指向与 me identifier 同一个 「Stack memory address」,有着同样的「Heap memory address值」指向 Heap 中的 「Heap memory address」,对应到同一个「物件值」这时若对friend
进行修改 ex.friend.age = 27
,将会修改到 Heap 中的「物件值」所以 console.log(me.age)
时,也将会是 27, 因为me
与friend
是指向同一个「物件值」三、const 没有失灵!
理解两种 Data Types 的储存方式,就会发现用 const 宣告的 object(Reference Types),如果只是改变
object 中的值,它在 stack 中的指向确实没有改变(都是存着「Heap memory address值」的「Stack memory address」)!但如果我们在宣告 object 后,重新赋值新的 object,就不行啰!
const me = { name: 'Kim', hobby: 'jogging',};me = {}; // Uncaught TypeError: Assignment to constant variable.
四、如何複製出新 object,而不是指向同一个?
使用Object.assign
!
⬇️ 合併两个 object,创造新 object
const me = { name: 'Kim', hobby: 'jogging',};const newMe = Object.assign({}, me);console.log(newMe); // print: {name: 'Kim', hobby: 'jogging'}
⬇️ 这两个变数最终指向不同的「Heap memory address」
newMe.hobby = 'eating';console.log(newMe); // {name: 'Kim', hobby: 'eating'} (newMe的hobby改变console.log(me); // {name: 'Kim', hobby: 'jogging'} (me的hobby没变
参考资料
The Complete JavaScript Course 2022: From Zero to Expert! Unit 99 & 100
以上是今天的分享,谢谢看完的你!