這篇是上完保哥的《JavaScript 開發實戰:核心概念篇》筆記之一 (狀態顯示為拖稿)
開始之前可以先看看 Stack Overflow 上這篇 Is JavaScript a pass-by-reference or pass-by-value language?
看完程式碼好想有點感覺,但真相是仍舊什麼都不懂 ( ̄□ ̄|||)a
以下就用保哥嫡傳畫圖理解來做說明 ㄟ( ̄▽ ̄ㄟ)
“物件是記憶體中的資料,跟變數關聯,並在執行時期擁有型別”
開始之前,先準備紙筆繪出以下樣板
大致可分為兩區塊:
- 程式碼區塊:就是用來寫 JavaScript 程式碼的…XD
- 變數、記憶體空間、型別:說明“物件是記憶體中的資料,跟變數關聯,並在執行時期擁有型別”
在以下程式碼片段執行的過程中,出現過幾個物件?幾個變數?幾種型別?
1 | var a; |
接下來就將程式碼一步一步寫下,並繪製對應圖形~
在程式碼區塊寫上
var a,並於變數畫上 a,因為沒給值因此是undefined,那undefined的型別叫undefined
將 1 assign 給 a,因此記憶體內會產生型別為
number的1,並且變數a指向1
將字串 a assign 給 a,因此記憶體內會產生型別為
string的a,並且變數a指向a;而原本的1則會被 GC (Garbage Collection),因此改為虛線
等號右邊先執行,因此記憶體內會再產生另一型別為
string的a(JavaScript 沒有所謂字串池觀念,因此會產生新的字串),並且跟原本變數a指向的字串a相加後產生新的字串aa
並將新產生的字串
aaassign 給 a (原本變數a指向的字串a及新產生的字串a都會被 GC)
最後整理一下圖形
計算一下即可得知程式碼執行過程中,一共產生了 5 個物件、1 個變數、3 個型別 <( ‵▽′)b good job
請注意 undefined 並不會被 GC! 因為永遠有個變數指向 undefined,即 window.undefined
接下來看看物件的圖形又應該怎麼畫
1 | window.myKey = 1; |
如法炮製先寫上程式碼
window.myKey = 1以及畫上變數window,這邊比較不一樣的是在記憶體空間內除了用物件的表示法外,值的部分是另外指向記憶體空間的資料
將 2 assign 給 myKey,因此記憶體內會產生型別為
number的2,並且變數myKey指向2;而原本的1則會被 GC
最後整理一下圖形

看完以上兩個範例,應該稍微了解圖形應該怎麼畫,再來就是要多練習囉~
1 | var a = { a1: 1, a2: 2 }; |
畫上變數
a、指向的物件及物件的值
畫上變數
b及指向的陣列 (注意到Array的型別仍舊是object)
在陣列
b加入兩次a
將陣列
b第一個元素的a1的值指向2;而原本的1則會被 GC
最後整理一下圖形,即可得知
b[1]['a1']是指向2
更多的練習題~
Example 1
1
2
3
4
5var a = { a1: 1, a2: 2 };
var b = [];
b.push(a);
b[0]['a1'] = 2;
// a['a1'] = ???
Example 2
1
2
3
4var a = { x: 1 };
var b = a;
a = { x: 2 };
// b.x = ???
- 變數
a指向新的物件{ x: 2 },因此不影響變數b.x - 因為變數
b仍指向物件{ x: 1 },因此物件{ x: 1 }不會被 GC
- 變數
Example 3
1
2
3
4
5
6var a = { a1: 1, a2: 2 };
function test(p) {
p.a1 = 2;
}
test(a);
// a.a1 = ???
- 變數
p因為是宣告在function內,因此當function執行完畢會被銷毀
- 變數
Example 4
1
2
3
4
5
6var a = 1;
function test(p) {
p = 2;
}
test(a);
// a = ???
- 變數
p指向的1跟原本變數a指向的1是不同的 - 在
function內產生的1和2會隨著function執行完畢而被 GC - 變數
p因為是宣告在function內,因此當function執行完畢會被銷毀
- 變數
進階題,理解同時 assign (如 jQuery 的 window.jQuery = window.$ = jQuery; )
- Example 5
1
2
3
4
5var a = { x: 1 };
var b = a;
a.x = a = { x: 2 };
// b.x = ???
// a.x = ???
畫上變數
a、指向的物件及物件的值畫上變數
b,並指向變數a指向的物件將【變數
a】及【變數a指向的物件{ x: 1}的變數x】同時指向新的物件{ x: 2 };而原本的1則會被 GC最後整理一下圖形,即可得知
b.x指向{ x: 2 },而a.x則是指向2
所謂 “一圖抵萬言”,透過圖形理解 JavaScript value reference,可以避免產生很多淺在性的 BUG (即當你想的跟執行的不一致 😂)