iT邦幫忙

2021 iThome 鐵人賽

DAY 24
0
Modern Web

追求JS小姊姊30天系列 第 24

追求JS小姊姊系列 Day24 -- 工具人、姐妹不只身份的差別(下):從記憶體看宣告變數的可變性

  • 分享至 

  • xImage
  •  

前情提要

被第一人視角的我打斷了對話,現在要繼續講完:
D22的時候,我們知道了識別字、保留字,其中識別字缺少了宣告這件事仍可以賦值,但是它會被存於全域,易造成污染。

x1 = 2;
//window查找是否有這個屬性
window.x1

所以宣告究竟能做到些什麼?


宣告 var & let & const 的差異

在下面我會將宣告的差異分成兩個面向來講解:

  1. 宣告變數的可變性
  2. 宣告變數的有效區域

在本日只會討論 1. 宣告變數的可變性 的部分,那就開始吧!


宣告變數的可變性

不可變的const
const宣告的數值,不可重新賦值跟重新宣告。

const x = 2;
x = 1;


當你試著重新賦值時,就會顯示上方的錯誤。

可變的let,var
varlet宣告的變數,其值可以視情況做修改;而宣告的部分:var可重複宣告,let不可重複宣告

var:

var x = 2;
var x = 1;

console.log(x);

let:

let y = 2;
let y = 1;
console.log(y);

但你有想過,可變與不可變背後 可能更好理解的原因嗎?

讓我們試著從記憶體的角度來看看吧?


變數是如何被存放的?

首先,你知道變數也需要存放地方嗎?那是在哪呢?!

圖片來源:https://tzutzu.coderbridge.io/2021/03/31/EventLoop/

以JavaScript來說分別就是

  1. Call Stack:負責存放基本型別(primitive)的值,像是1,"字串"
  2. Memory Heap:存放複合型別(non-primitive)的值,像是object等。

所以,當你每次宣告變數,並賦予基本型別值時,JS引擎其實在背後都會為變數新增記憶體空間

例如當你宣告了一個變數為2時,其實是:

let x = 2;//const or var 也是

而當你重新賦值時,實際正同時發生以下的事情:

let x = 2;
x = 1;

這時候實際上會再新建0x002的記憶體位置,並將1存入,接著x轉為指向0x002的記憶體位置。

將變數值賦予另一個變數

let x = 2;

//把x值傳給y
let y = x;


兩個不同變數皆會指向相同記憶體位置。

修改x的值時

x將值賦予給別人後,將本身的值從2改為1

let x = 2;

//把x值傳給y
let y = x;

x = 1;


從記憶體看 let & const 不變與可變

還記得上面講到:用let宣告的變數可修改,但const則不行這件事嗎?所謂的可變與不可變其實是指:記憶體位置

let允許你修改記憶體位置,但const則不行

我們先試著用const再寫一次同樣的內容:

const x = 2;
x = 1;


前面提過 let,const兩種宣告的值是否能修改,其實是跟記憶體位置有關,因此這時自然就會報錯啦~

然而,真的就這樣嗎?

我們同樣用const宣告,這次要建立的是一個複合型別的空陣列

const x = [];

接著我們透過push幫它新增值1,2,然後印出結果

x.push(1);
x.push(2);

console.log(x);


結果卻沒有報錯,怎麼回事呢? 一樣再從記憶體來看

當你宣告了一個空陣列時,其實是長這樣的

const x = [];

此時,你在Call Stack儲存的其實是Heap的記憶體位置,而不再是一個值。
所以當使用push添加值卻不會報錯,是因為push影響的是Heap。

x.push(1);
x.push(2);

所以當我們試著重新賦值[] 時就會報錯啦~

const x = [];
x = [];


因為x = []對於記憶體來說是其實會讓callstack再新增一個記憶位置,並將x指向它,因此就會報錯

從上面的示範,應該就能簡單說明,為何同樣以const宣告,基本型別與複合型別卻有不同的結果吧~


:但這樣還是沒有解釋到為何宣告能預防全域污染這件事啊...
方函式:別急,至少現在你能理解工具人與姐妹之間的差異是:~~

  1. 是否具有能力(methods,properties)
  2. 變數儲存的記憶體位置也不同

-- to be continued --


那今天就到這邊摟!
每天的休息,是為了後面的追求,明天見。


reference:
  1. JavaScript’s Memory Model
  2. [筆記] 談談 JavaScript 中 by reference 和 by value 的重要觀念
  3. 深入探討 JavaScript 中的參數傳遞:call by value 還是 reference?
  4. JavaScript 核心觀念(29)-物件-Call by Reference 還是 Call by Sharing

上一篇
追求JS小姊姊系列 Day23 -- 頭等工具人也看安眠書店? 認識閉包讓你獨佔變數
下一篇
追求JS小姊姊系列 Day25 -- 工具人、姐妹的存活原理:宣告變數的有效區域
系列文
追求JS小姊姊30天30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言