昨日我們學習了資料的型態,今天我們要來了解變數的參考。
我們先建立一個a變數,並且把b指向a
var a = 3
var b = a
console.log(a,b); // 3 3
沒錯跟我們所想的一樣
但如果我們把變數a 改掉呢???
var a = 3
var b = a
a = a + 1
console.log(a,b); //4 3
是不是跟你所想的不太一樣???
為什麼我明明是指向a,但改變變數a,變數b卻沒有影響
「這是因為在JavaScript中, String、Number、Null是使用淺複製,也就是 = 只是複製資料給其宣告變數。」
嗯 ? 是這樣嗎
var a = 3
var b = a
a = a + 1
console.log(a,b); //4 3
var a = null
var b = a
a = 1
console.log(a); //1
console.log(b); //null
在上面我們介紹了by value的型態,接下來我們來了解by reference的行為。
在這邊先插播一下,在我們這個世界裡會針對各種現象去做不同名詞的解釋。
而我們要了解程式運作原理,就要知道電腦如何把資料儲存在記憶體中。
物件的傳址方式,也就是a和b共同指向同一個記憶體!!!
var a = {name: 'Dennis'}
var b = a
console.log(a,b); //{ name: 'Dennis' } { name: 'Dennis' }
a.name = 'Ian'
console.log(a,b);//{ name: 'Ian' } { name: 'Ian' }
var a = [1,2]
var b = a
console.log(a,b);//[ 1, 2 ] [ 1, 2 ]
a = [1,2,3]
console.log(a,b); //[ 1, 2, 3 ] [ 1, 2 ]
不是說Array是Pass by Reference嗎???
我們說的pass by reference是說指向記憶體,並不是指向a的變數,而是指向a所指向的記憶體位址!!!
以下圖來說
比如陣列[1,2]在電腦中的位址為100號,而我宣告變數a會指向100號,再宣告b把a指向的記憶體位址交給b,所以a和b都指向100號。
但中途又把a指向[1,2,3]也就是101號的位址,那當然a和b會得到不同的資料瞜!!!
因為b並不是指向a,而是取得a指向的位址!!!
以下面的程式來說就符合共同指向
var a = [1,2]
b = a
a.push(3)
console.log(a,b); //[ 1, 2, 3 ] [ 1, 2, 3 ]
假設陣列[1,2]為100號,我在100號新增了一個數值那還是在100號,所以a和b共同獲得同一位址,當然指向100號!!!
使用一級函式可能跟你想的不太一樣
var a = function test() {
console.log('hi');
}
var b = a
a = function test() {
console.log('hello');
}
a() //hello
b() //hi
如果用我們上面所述的指標與記憶體位址來看待,就會很好了解。
以下程式代表電腦會為資料創造一個空間,就算都是一樣的資料、名稱,也會是不同記憶體位址。
var a = function test() {
console.log('hello');
}
var b = function test() {
console.log('hello');
}
console.log(a === b); //false
var a = function test() {
console.log('hello');
}
var b = a
a() // hello
b() //hello
function test() {
console.log('hi');
}
a = test
a() //hi
b() //hello
我相信很多人都會被pass by reference 或是 pass by value搞混。
這邊提供給各位一個觀念,只要記得電腦儲存資料都會使用記憶體位置,當資料不同的時候想必會有不同的位址。
就像每間房子裡面住不同的人,你要找阿明、阿華都是不同的家、不同的門牌號碼。
照著這個脈絡其實我們就可以很明確的知道其實一切都是指標與記憶體。
而陣列、物件、函式裡面的資料,都像是房子裡面的所屬物,而房子門牌一樣不會變。
所以把 = 看作指向某個位址這樣會更好的貼近電腦的操作,而我們也不會被各種看起來很多專有名詞解釋的現象搞混!!!
當然我也是絞盡腦汁才敢大膽做結語,如果有更好的解釋可以在下面留言,我會再做修改。