1、基本數(shù)據(jù)類(lèi)型和引用數(shù)據(jù)類(lèi)型
ECMAScript包括兩個(gè)不同類(lèi)型的值:基本數(shù)據(jù)類(lèi)型和引用數(shù)據(jù)類(lèi)型。
基本數(shù)據(jù)類(lèi)型指的是簡(jiǎn)單的數(shù)據(jù)段,引用數(shù)據(jù)類(lèi)型指的是有多個(gè)值構(gòu)成的對(duì)象。
當(dāng)我們把變量賦值給一個(gè)變量時(shí),解析器首先要確認(rèn)的就是這個(gè)值是基本類(lèi)型值還是引用類(lèi)型值。
2、常見(jiàn)的基本數(shù)據(jù)類(lèi)型:
Number、String 、Boolean、Null和Undefined。基本數(shù)據(jù)類(lèi)型是按值訪問(wèn)的,因?yàn)榭梢灾苯硬僮鞅4嬖谧兞恐械膶?shí)際值。示例:
var a = 10;
var b = a;
b = 20;
console.log(a); // 10值
上面,b獲取的是a值得一份拷貝,雖然,兩個(gè)變量的值相等,但是兩個(gè)變量保存了兩個(gè)不同的基本數(shù)據(jù)類(lèi)型值。
b只是保存了a復(fù)制的一個(gè)副本。所以,b的改變,對(duì)a沒(méi)有影響。
3、引用類(lèi)型數(shù)據(jù):
也就是對(duì)象類(lèi)型Object type,比如:Object 、Array 、Function 、Data等。
javascript的引用數(shù)據(jù)類(lèi)型是保存在堆內(nèi)存中的對(duì)象。
與其他語(yǔ)言的不同是,你不可以直接訪問(wèn)堆內(nèi)存空間中的位置和操作堆內(nèi)存空間。只能操作對(duì)象在棧內(nèi)存中的引用地址。
所以,引用類(lèi)型數(shù)據(jù)在棧內(nèi)存中保存的實(shí)際上是對(duì)象在堆內(nèi)存中的引用地址。通過(guò)這個(gè)引用地址可以快速查找到保存中堆內(nèi)存中的對(duì)象。
var obj1 = new Object();
var obj2 = obj1;
obj2.name = "我有名字了";
console.log(obj1.name); // 我有名字了
說(shuō)明這兩個(gè)引用數(shù)據(jù)類(lèi)型指向了同一個(gè)堆內(nèi)存對(duì)象。obj1賦值給onj2,實(shí)際上這個(gè)堆內(nèi)存對(duì)象在棧內(nèi)存的引用地址復(fù)制了一份給了obj2,
但是實(shí)際上他們共同指向了同一個(gè)堆內(nèi)存對(duì)象。實(shí)際上改變的是堆內(nèi)存對(duì)象。
4、總結(jié)區(qū)別
a 聲明變量時(shí)不同的內(nèi)存分配:
1)原始值:存儲(chǔ)在棧(stack)中的簡(jiǎn)單數(shù)據(jù)段,也就是說(shuō),它們的值直接存儲(chǔ)在變量訪問(wèn)的位置。
這是因?yàn)檫@些原始類(lèi)型占據(jù)的空間是固定的,所以可將他們存儲(chǔ)在較小的內(nèi)存區(qū)域 – 棧中。這樣存儲(chǔ)便于迅速查尋變量的值。
2)引用值:存儲(chǔ)在堆(heap)中的對(duì)象,也就是說(shuō),存儲(chǔ)在變量處的值是一個(gè)指針(point),指向存儲(chǔ)對(duì)象的內(nèi)存地址。
這是因?yàn)椋阂弥档拇笮?huì)改變,所以不能把它放在棧中,否則會(huì)降低變量查尋的速度。相反,放在變量的棧空間中的值是該對(duì)象存儲(chǔ)在堆中的地址。
地址的大小是固定的,所以把它存儲(chǔ)在棧中對(duì)變量性能無(wú)任何負(fù)面影響。
b 不同的內(nèi)存分配機(jī)制也帶來(lái)了不同的訪問(wèn)機(jī)制
1)在javascript中是不允許直接訪問(wèn)保存在堆內(nèi)存中的對(duì)象的,所以在訪問(wèn)一個(gè)對(duì)象時(shí),
首先得到的是這個(gè)對(duì)象在堆內(nèi)存中的地址,然后再按照這個(gè)地址去獲得這個(gè)對(duì)象中的值,這就是傳說(shuō)中的按引用訪問(wèn)。
2)而原始類(lèi)型的值則是可以直接訪問(wèn)到的。
c 復(fù)制變量時(shí)的不同
1)原始值:在將一個(gè)保存著原始值的變量復(fù)制給另一個(gè)變量時(shí),會(huì)將原始值的副本賦值給新變量,此后這兩個(gè)變量是完全獨(dú)立的,他們只是擁有相同的value而已。
2)引用值:在將一個(gè)保存著對(duì)象內(nèi)存地址的變量復(fù)制給另一個(gè)變量時(shí),會(huì)把這個(gè)內(nèi)存地址賦值給新變量,
也就是說(shuō)這兩個(gè)變量都指向了堆內(nèi)存中的同一個(gè)對(duì)象,他們中任何一個(gè)作出的改變都會(huì)反映在另一個(gè)身上。
(這里要理解的一點(diǎn)就是,復(fù)制對(duì)象時(shí)并不會(huì)在堆內(nèi)存中新生成一個(gè)一模一樣的對(duì)象,只是多了一個(gè)保存指向這個(gè)對(duì)象指針的變量罷了)。多了一個(gè)指針
d 參數(shù)傳遞的不同(把實(shí)參復(fù)制給形參的過(guò)程)
**** ****
首先我們應(yīng)該明確一點(diǎn):ECMAScript中所有函數(shù)的參數(shù)都是按值來(lái)傳遞的。
但是為什么涉及到原始類(lèi)型與引用類(lèi)型的值時(shí)仍然有區(qū)別呢?還不就是因?yàn)閮?nèi)存分配時(shí)的差別。
(1)原始值:只是把變量里的值傳遞給參數(shù),之后參數(shù)和這個(gè)變量互不影響。
(2)引用值:對(duì)象變量它里面的值是這個(gè)對(duì)象在堆內(nèi)存中的內(nèi)存地址,這一點(diǎn)要時(shí)刻銘記在心!
因此它傳遞的值也就是這個(gè)內(nèi)存地址,這也就是為什么函數(shù)內(nèi)部對(duì)這個(gè)參數(shù)的修改會(huì)體現(xiàn)在外部的原因了,因?yàn)樗鼈兌贾赶蛲粋€(gè)對(duì)象。