-
類型轉(zhuǎn)換
-
轉(zhuǎn)換為string、boolean

類型轉(zhuǎn)換中的一些特殊情況:
- 其他類型轉(zhuǎn)換為boolean時(shí)為false的有:
number :0,NaN;
!!0
false
!!NaN
false
string :""(空字符串);
!!''
false
!!' ' //空格字符串為true
true
null、undefined:均為false;
!!null
false
!!undefined
false
值為 false 總結(jié):
if (false)
if (null)
if (undefined)
if (0)
if (NaN)
if ('')
if ("")
if (document.all) [1]
- object全部為true
-
轉(zhuǎn)換為number
一般情況下,只會(huì)將0-9組成的字符串轉(zhuǎn)換成 number,轉(zhuǎn)換方法有:
Number('1')===1;-
parseInt('011',10)===11;;parseInt('011',8)===9;;parseInt('011',2)===3; parseFloat('1.23')===1.23;'1'-0===1;-
+'1'===1;;+'-1'===-1;
以上5中方法是將只有0-9組成的字符串轉(zhuǎn)換成 number的方法,然而對于包含非數(shù)字的字符串,parseInt()、parseFloat() 方法依然有效;
比如:
Number('111a')
NaN
-------------
parseInt('011sd')
11
parseInt('011sd11',2)
3
-----------
parseFloat('011.4sd.23')
11.4
---------
'122ff'-0
NaN
-----------------
+'01a'
NaN
注意:parseInt()、parseFloat()會(huì)從左往右開始轉(zhuǎn)換遇到的數(shù)字,直到非數(shù)字就結(jié)束。
-
內(nèi)存圖
此處,只通過以下幾張圖簡單了解JS的在所分配的內(nèi)存中的一些存儲過程。
-
內(nèi)存分配簡圖
js-21-01.png
內(nèi)存是讀寫速度最快的,當(dāng)前運(yùn)行的程序都會(huì)拷貝到內(nèi)存中運(yùn)行。開機(jī)就是將操作系統(tǒng)讀取到內(nèi)存中運(yùn)行。
- 假定瀏覽器給JS分配了100M內(nèi)存,那JS是如何使用的??
js-21-02.png
JS會(huì)將分到的內(nèi)存劃分為代碼區(qū)和數(shù)據(jù)區(qū),比如代碼var a=1;,a 就存在代碼區(qū),數(shù)字1則存在數(shù)據(jù)區(qū),兩者之間會(huì)有某種關(guān)聯(lián)。 -
數(shù)據(jù)區(qū)又是如何存儲的??
js-21-03.png
數(shù)據(jù)區(qū)會(huì)劃分為2塊,棧內(nèi)存和堆內(nèi)存;
當(dāng)瀏覽器開始運(yùn)行代碼區(qū)的代碼時(shí),第一步首先是:變量提升;之后才開始運(yùn)行,運(yùn)行時(shí)也就開始將數(shù)據(jù)存儲在數(shù)據(jù)區(qū);

如上圖,數(shù)字1、2、.......在JS中都是以固定的64位2進(jìn)制來存儲的,然而其他內(nèi)型并不都是按固定長度二進(jìn)制來存儲的,那么如圖:如果隨著運(yùn)行按順序存儲每一步的數(shù)據(jù),當(dāng)給 對象 o 增加新的鍵值對時(shí),就需要在第一次存 o 的位置插入一段空間,這就很尷尬了...............
因此實(shí)際存儲時(shí),根據(jù)數(shù)據(jù)類型荀澤對應(yīng)的存儲區(qū):

如上圖,實(shí)際對對象 o 的存儲是分2部分的,棧內(nèi)存中存的是一個(gè)地址,這個(gè)地址指向堆內(nèi)存中存放具體數(shù)據(jù)的一段空間。
當(dāng)執(zhí)行o2 = o;,時(shí):

會(huì)將棧內(nèi)存中 o 的數(shù)據(jù)(即地址)拷給 o2 ,之后 o 和 o2 實(shí)際指向堆內(nèi)存中同一空間。
-
JS中7種數(shù)據(jù)類型的存儲方式
image.png
對于6種簡單類型,直接存在stack中,關(guān)于string此處暫不討論;
對于Object類型,存在stack中的是對應(yīng)的heap中的一個(gè)空間的地址,也就是Object的實(shí)際內(nèi)容是存儲在heap中,因此Object是對heap中一段空間的引用。 幾個(gè)案例
-
如下圖:
image.png
-
如下圖:
image.png
首先,回顧這一句:“=”只是把右邊的對應(yīng)的東西放到左邊的對應(yīng)的空間里。左邊是b,那么b對應(yīng)的空間是???
b對應(yīng)的空間是: stack 給b分配的一小段空間;而右邊的是一個(gè)匿名 對象 ,首先給匿名對象在 heap 分配一個(gè)空間存放內(nèi)容;之后再執(zhí)行“=”。 -
如下圖:
image.png
b.name對應(yīng)的空間是: b在stack里存的地址所指向的heap中的一個(gè)空間里的名為“name”的key所對應(yīng)的空間;而右邊的是一個(gè)字符串 ,字符串是簡單類型;直接執(zhí)行“=”。
-
如下圖:
image.png
-
關(guān)于對象里的self
看下圖:
image.png
image.png
對比上面兩附圖,為什么結(jié)果不同???
首先,在運(yùn)行前,將變量提升,則第一幅圖可以等價(jià)于:
var a
a = {self:a} //此時(shí)在heap中寫“=”右邊的對象時(shí),a的值還是undefined
-
一個(gè)測試題
如下圖:
image.png
解析:當(dāng)運(yùn)行a.x = a = {n:2};時(shí),瀏覽器是先看左邊再看右邊的,然后再把右邊的東西傳給左邊的容器;也就是說先確定左邊是個(gè)什么東西,再確定右邊是個(gè)什么東西,然后從右邊開始往左邊塞東西;首先,看“=”左邊的 a.x 時(shí)已經(jīng)明確了此時(shí)的a = ADDR 34,然后在看中間的 a 明確了中間的a = ADDR 34,再然后看右邊的東西,發(fā)現(xiàn)右邊的是個(gè)匿名對象,即在 Heap 里面創(chuàng)建這個(gè)對象,這樣左、中、右都明確了,然后再執(zhí)行a = {n:2};時(shí),a = ADDR 54,然而,之前的 a.x 的指向并不會(huì)再次變更,導(dǎo)致鍵值對 x:{n:2} 添加在 ADDR 34里面。 -
垃圾回收
image.png
測試題:
var fn = function(){}
document.body.onclick = fn
fn = null
此時(shí),var fn = function(){} 里面的function(){} 是否是垃圾???

那么,當(dāng)瀏覽器中的這個(gè)頁面關(guān)閉時(shí),var fn = function(){} 里面的function(){} 是否是垃圾??
答:yes,頁面關(guān)閉時(shí),即document = null,所以之前的functiong就沒有被引用了。除了IE6;
在IE6中當(dāng)前頁面關(guān)閉,瀏覽器未關(guān)閉時(shí),var fn = function(){} 里面的function(){} 還會(huì)保留,這樣導(dǎo)致 內(nèi)存 會(huì)被浪費(fèi),解決方法:

window.onload = function(){
document.body.onclick = null;
.
.
.
有多少個(gè)就重新賦值 null 多少個(gè)
}
- 淺拷貝 & 深拷貝
-
深拷貝:
image.png -
淺拷貝:
image.png













