iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 2
0
Modern Web

從技術文章深入學習 JavaScript系列 第 2

Day 02 [整理 01] JavaScript變量存儲

  • 分享至 

  • xImage
  •  

Day 02 [整理 01] JavaScript變量存儲

變量有甚麼類型

  1. 基本類型

    undefine,string,boolean,null,number

  2. 引用類型

    Object包括它的延伸(比方說array...)

探討的問題

當我們給變量賦值另一個變量,會發生發生甚麼

注意:

​ 在JS裡面,一個變量的值絕對不會指向另一個變量,而是指向內存

解析

情況一: 基本類型

let num1 = 5
let num2 = num1

我們用num1這個變量初始化了num2,技術上來說會指向同一個內存地址

https://ithelp.ithome.com.tw/upload/images/20200912/20124350dS8iXDKnzK.png

如果今天對num2 進行操作,num1會因此改變嗎?

let num1 = 'foo'
let num2 = num1
num2 = num2 + 'bar'

答案是不會的,因為基本類型是不可變的,所以num2會自行指向自身的內存地址

https://ithelp.ithome.com.tw/upload/images/20200912/20124350erMDWqw5gv.png

這時候可以打印看看num1是否真的不會變

let num1 = 'foo'
let num2 = num1
num2 + 'bar'
console.log('num1:',num1)

結果:

https://ithelp.ithome.com.tw/upload/images/20200912/20124350wy95ENa3yn.png

情況二: 引用類型

預先知識

引用類型賦值時的情況比較特別,會先引用到stack的某一個地址,再透過那個地址的值(heap的地址)查找到heap的值,比方說下面這樣

let obj1 = {
  foo: 1
}

let obj2 = {
  foo: 1
}

console.log(obj1 === obj2); // false
obj1.bar = 2 // 為了證明那兩個是不同(相同的話obj2會被obj1影響)
console.log(obj2); // {foo: 1}

示意圖:

https://ithelp.ithome.com.tw/upload/images/20200912/20124350cD6yHI248t.png

正題

假如把一個變量用另一個變量賦值會怎麼樣?

let obj1 = {
  foo: 1
}
let obj2 = obj1 // 把obj1的內存地址給了他

console.log(obj1 === obj2); // 這個就變成true
obj1.bar = 2
console.log(obj2); // 這個也會受到obj1的操作影響

示意圖

https://ithelp.ithome.com.tw/upload/images/20200912/20124350w8pIJTtByn.png

注意:

上面之所以沒變,是因為我們都是對heap進行操作,所以obj2當然會被影響,假設我對下面對象這樣操作結果就會不一樣!!!

let obj1 = {
  foo: 1
}
let obj2 = obj1 // 內存複製

obj1.bar = 2 // 將heap內的值改變(因為obj2指向的stack部變所以也會受到影響)

// 這裡非常關鍵,obj2在stack裡指向的地址發生改變,所以之後假設對這個對象操作,已經不是obj1指向的那個對象,obj1理所當然不會改變
obj2 = {  
  foo: 1,
  bar: 2,
}
obj2.baz = 3
console.log(obj1); //{foo: 1, bar: 2} 沒有baz!!
 

示意圖

  1. 內存賦值完成( let obj2 = obj1 )

    https://ithelp.ithome.com.tw/upload/images/20200912/20124350ZW7RMUfvXc.png

  2. 將heap內的值改變( obj1.bar = 2 )

    https://ithelp.ithome.com.tw/upload/images/20200912/20124350jh7D2hrTOy.png

  3. obj2被賦予新的值( obj2= {foo: 1,bar: 2} )

    https://ithelp.ithome.com.tw/upload/images/20200912/20124350LNDMLlXLzt.png

  4. 操作obj2對應的對象( obj2.baz = 3 )

    https://ithelp.ithome.com.tw/upload/images/20200912/20124350t7YTC659iK.png

  5. 結論

    最後打印obj1的時候跑出來的是 {foo:1, bar: 2} !

參考資源


上一篇
Day 01 [介紹] 30天深入 JavaScript 文章概覽
下一篇
Day 03 [原型鍊01] JavaScript 世界萬物誕生記
系列文
從技術文章深入學習 JavaScript29
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
fillano
iT邦超人 1 級 ‧ 2020-09-15 14:31:40
let num1 = 'foo'
let num2 = num1
num2 + 'bar' //<--這裡
console.log('num1:',num1)

沒有assign,那連num2都不會改變哪...這個範例看起來有點怪

s95050937 iT邦新手 5 級 ‧ 2020-09-15 19:58:32 檢舉

已修改成以下:

let num1 = 'foo'
let num2 = num1
num2 = num2 + 'bar' //<--這裡
console.log('num1:',num1)

主要想表達意思是 num2 改變之後不會影響 num1

我要留言

立即登入留言