JS之變量如何賦值

JS之變量如何賦值

變量有甚麼類型

  1. 基本類型

    Undefine,String,Boolean,Null,Number

  2. 引用類型

    Object包括它的延伸

探討的問題

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

注意:

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

解析

情況一: 基本類型

1
2
let num1 = 5
let num2 = num1

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

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

1
2
3
let num1 = 'foo'
let num2 = num1
num2 + 'bar'

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

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

1
2
3
4
let num1 = 'foo'
let num2 = num1
num2 + 'bar'
console.log('num1:',num1)

結果:

情況二: 引用類型

預先知識

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

1
2
3
4
5
6
7
8
9
10
11
let obj1 = {
foo: 1
}

let obj2 = {
foo: 1
}

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

示意圖:

正題

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

1
2
3
4
5
6
7
8
let obj1 = {
foo: 1
}
let obj2 = obj1 // 把obj1的內存地址給了他

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

示意圖

注意:

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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 )

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

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

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

  5. 結論

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