變量可能包含兩種不同數(shù)據(jù)類(lèi)型的值:基本類(lèi)型值和引用類(lèi)型值舶治。
基本類(lèi)型值:簡(jiǎn)單數(shù)據(jù)段
五種基本數(shù)據(jù)類(lèi)型是按值訪問(wèn)的分井,因?yàn)榭梢圆僮鞅4嬖谧兞恐档脤?shí)際的值车猬。
引用類(lèi)型值:可能由多個(gè)值構(gòu)成的對(duì)象
引用類(lèi)型的值是保存在內(nèi)存中的對(duì)象。與其他語(yǔ)言不同尺锚,js不允許直接訪問(wèn)內(nèi)存中的位置珠闰,也就是說(shuō)不能直接操作對(duì)象的內(nèi)存空間。在操作對(duì)象時(shí)瘫辩,實(shí)際上是在操作對(duì)象的引用而不是實(shí)際的對(duì)象伏嗜。因此,引用類(lèi)型的值是按引用訪問(wèn)的伐厌。
1.只能給引用類(lèi)型值動(dòng)態(tài)地添加屬性承绸。
2.上面說(shuō)的是保存的方式不同,在從一個(gè)變量向另一個(gè)變量復(fù)制基本類(lèi)型值和引用類(lèi)型值時(shí)挣轨,也存在不同军熏。
從一個(gè)變量向另一個(gè)變量復(fù)制基本類(lèi)型值時(shí),會(huì)在變量對(duì)象上創(chuàng)建一個(gè)新值卷扮,然后把該值復(fù)制到為新變量分配的位置上羞迷,這兩個(gè)變量可以參與任何操作而不會(huì)相互影響。
從一個(gè)變量向另一個(gè)變量復(fù)制引用類(lèi)型的值時(shí)画饥,同樣也會(huì)將存儲(chǔ)在變量對(duì)象中的值復(fù)制一份放到位新變量分配的空間中。不同的是浊猾,這個(gè)值的副本實(shí)際上是一個(gè)指針抖甘,而這個(gè)指針指向存儲(chǔ)在堆中的一個(gè)對(duì)象。復(fù)制操作結(jié)束后葫慎,兩個(gè)變量實(shí)際上將引用同一個(gè)對(duì)象衔彻,因此,改變其中一個(gè)變量偷办,就會(huì)影響另一個(gè)變量艰额。
3.傳遞參數(shù)
所有函數(shù)的參數(shù)都是按值傳遞的。也就是說(shuō)椒涯,把函數(shù)外部的值復(fù)制給函數(shù)內(nèi)部的參數(shù)柄沮,就和把值從一個(gè)變量復(fù)制到另一個(gè)變量一樣》掀瘢基本類(lèi)型值的傳遞如同基本類(lèi)型變量的復(fù)制一樣祖搓,引用類(lèi)型值的傳遞如同引用類(lèi)型變量的復(fù)制一樣。
訪問(wèn)變量有按值和按引用兩種方式湖苞,而參數(shù)只能按值傳遞拯欧。
在向參數(shù)傳遞基本類(lèi)型的值時(shí),被傳遞的值會(huì)被復(fù)制給另一個(gè)局部變量(即命名參數(shù)财骨,或者說(shuō)是arguments對(duì)象中的一個(gè)元素)镐作。在向參數(shù)傳遞引用類(lèi)型的值時(shí)藏姐,會(huì)把這個(gè)值在內(nèi)存中的地址復(fù)制給一個(gè)局部變量,因此這個(gè)局部變量的變化會(huì)反映在函數(shù)的外部该贾。
4.檢測(cè)類(lèi)型
檢測(cè)一個(gè)變量是不是基本數(shù)據(jù)類(lèi)型:typeof操作符是最佳的工具
檢測(cè)引用類(lèi)型的值時(shí)羔杨,instanceof操作符,如果變量時(shí)給定引用類(lèi)型的實(shí)例靶庙,那么instanceof操作符就會(huì)返回true
執(zhí)行環(huán)境及作用域
在web瀏覽器中问畅,全局執(zhí)行環(huán)境被認(rèn)為是window對(duì)象,因此所有全局變量和函數(shù)都是作為window對(duì)象的屬性和方法創(chuàng)建的六荒。
某個(gè)執(zhí)行環(huán)境的所以代碼執(zhí)行完畢后护姆,該環(huán)境被銷(xiāo)毀,保存在其中的所有變量和函數(shù)定義也隨之銷(xiāo)毀(全局執(zhí)行環(huán)境直到應(yīng)用程序退出-例如關(guān)閉網(wǎng)頁(yè)或?yàn)g覽器-時(shí)才會(huì)被銷(xiāo)毀)
每個(gè)函數(shù)都有自己的執(zhí)行環(huán)境掏击。當(dāng)執(zhí)行流進(jìn)入一個(gè)函數(shù)時(shí)卵皂,函數(shù)的環(huán)境就會(huì)被推入一個(gè)環(huán)境棧中,而在函數(shù)執(zhí)行之后砚亭,棧將其環(huán)境彈出灯变,把控制權(quán)返回給之前的執(zhí)行環(huán)境。
當(dāng)代碼在一個(gè)環(huán)境中執(zhí)行時(shí)捅膘,會(huì)創(chuàng)建變量對(duì)象的一個(gè)作用域鏈添祸。作用域鏈的用途,是保證對(duì)執(zhí)行環(huán)境有權(quán)訪問(wèn)的所有變量和函數(shù)的有序訪問(wèn)寻仗。作用域鏈的前端刃泌,始終都是當(dāng)前執(zhí)行的代碼所在環(huán)境的變量對(duì)象。如果這個(gè)環(huán)境是函數(shù)署尤,則將其活動(dòng)對(duì)象作為變量對(duì)象耙替。
作用域鏈中的下一個(gè)變量對(duì)象來(lái)自包含(外部)環(huán)境,而再下一個(gè)變量對(duì)象則來(lái)自下一個(gè)包含環(huán)境曹体。這樣俗扇,一直延續(xù)到全局執(zhí)行環(huán)境,全局執(zhí)行環(huán)境的變量對(duì)象始終都是作用域鏈中的最后一個(gè)對(duì)象箕别。
執(zhí)行環(huán)境的類(lèi)型共有兩種:全局和局部铜幽,但還是有辦法來(lái)延長(zhǎng)作用域鏈。
沒(méi)有塊級(jí)作用域
在c++中串稀,color會(huì)在if語(yǔ)句執(zhí)行完畢后被銷(xiāo)毀啥酱,在js中,if語(yǔ)句中的變量聲明會(huì)將變量添加到當(dāng)前的執(zhí)行環(huán)境(在這里是全局環(huán)境)中厨诸。for語(yǔ)句更要牢記這一點(diǎn)镶殷。
1.聲明變量
使用var聲明的變量會(huì)自動(dòng)被添加到最接近的環(huán)境中。在函數(shù)內(nèi)部微酬,最接近的環(huán)境就是函數(shù)的局部環(huán)境绘趋;在with語(yǔ)句中颤陶,最接近的環(huán)境是函數(shù)環(huán)境。如果初始化變量時(shí)沒(méi)有使用var聲明陷遮,該變量會(huì)自動(dòng)地被添加到全局環(huán)境滓走。
2.查詢標(biāo)識(shí)符
當(dāng)在某個(gè)環(huán)境中為了讀取或?qū)懭攵靡粋€(gè)標(biāo)識(shí)符時(shí),必須通過(guò)搜索來(lái)確定該標(biāo)識(shí)符實(shí)際代表什么帽馋。搜索過(guò)程從作用域鏈的前端開(kāi)始搅方,向上逐級(jí)查詢與給定名字匹配的標(biāo)識(shí)符。如果在局部環(huán)境中找到了該標(biāo)識(shí)符绽族,搜索過(guò)程停止姨涡,變量就緒,如果在局部環(huán)境中沒(méi)有找到該變量名吧慢,則繼續(xù)沿作用域鏈向上搜索涛漂,搜索過(guò)程將一直追溯到全局環(huán)境的變量對(duì)象
如果在局部環(huán)境中找到了那個(gè)變量名,但是想訪問(wèn)全局環(huán)境下的此變量检诗,可以使用window.變量名來(lái)訪問(wèn)全局變量匈仗。
3.垃圾收集
js具有自動(dòng)垃圾收集機(jī)制,即執(zhí)行環(huán)境會(huì)負(fù)責(zé)管理代碼執(zhí)行過(guò)程中使用的內(nèi)存逢慌。
而在c和c++之類(lèi)的語(yǔ)言中悠轩,開(kāi)發(fā)人員的一項(xiàng)基本任務(wù)就是手動(dòng)跟蹤內(nèi)存的使用情況,這是造成許多問(wèn)題的一個(gè)根源攻泼。
在編寫(xiě)js程序時(shí)哗蜈,開(kāi)發(fā)人員不用再關(guān)心內(nèi)存使用問(wèn)題,所需內(nèi)存的分配以及無(wú)用內(nèi)存的回收完全實(shí)現(xiàn)了自動(dòng)管理坠韩。
這種垃圾收集機(jī)制的原理其實(shí)很簡(jiǎn)單:找出那些不再繼續(xù)使用的變量,然后釋放其占用的內(nèi)存炼列。為此只搁,垃圾收集器會(huì)按照固定的時(shí)間間隔(或代碼執(zhí)行中預(yù)定的收集時(shí)間),周期性地執(zhí)行這一操作俭尖。
函數(shù)中局部變量的正常生命周期:
局部變量只在函數(shù)執(zhí)行的過(guò)程中存在氢惋。而在這個(gè)過(guò)程中,會(huì)為局部變量在棧(或堆)內(nèi)存上分配相應(yīng)的空間稽犁,以便存儲(chǔ)他們的值焰望。然后在函數(shù)中使用這些變量,直至函數(shù)執(zhí)行結(jié)束已亥。此時(shí)熊赖,局部變量就沒(méi)有存在的必要了,因此可以釋放他們的內(nèi)存以供將來(lái)使用虑椎。在這種情況下震鹉,很容易判斷變量是否還有存在的必要俱笛;但并非所有情況下都這么容易就能得出結(jié)論。垃圾收集器必須跟蹤哪個(gè)變量有用哪個(gè)變量沒(méi)用传趾,對(duì)于不再有用的變量打上標(biāo)記迎膜,以備將來(lái)收回其占用的內(nèi)存。用于標(biāo)識(shí)無(wú)用變量的策略可能會(huì)因?qū)崿F(xiàn)而異浆兰,但具體到瀏覽器中的實(shí)現(xiàn)磕仅,則通常有兩個(gè)策略。
(1)標(biāo)記清除簸呈,js中最常用的垃圾收集方式榕订。當(dāng)變量進(jìn)入環(huán)境時(shí),就將這個(gè)變量標(biāo)記為“進(jìn)入環(huán)境”蝶棋。從邏輯上講卸亮,永遠(yuǎn)不能釋放進(jìn)入環(huán)境的變量所占用的內(nèi)存,因?yàn)橹灰獔?zhí)行流進(jìn)入相應(yīng)的環(huán)境玩裙,就可能會(huì)用到他們兼贸。而當(dāng)變量離開(kāi)環(huán)境時(shí),則將其標(biāo)記為“離開(kāi)環(huán)境”吃溅。
(2)引用計(jì)數(shù)溶诞,不太常見(jiàn)的垃圾收集策略。引用計(jì)數(shù)的含義是跟蹤記錄每個(gè)值被引用的次數(shù)决侈。當(dāng)聲明了一個(gè)變量并將一個(gè)引用類(lèi)型值賦給該變量時(shí)螺垢,則這個(gè)值得引用次數(shù)就是1.如果同一個(gè)值又被賦給另一個(gè)變量,則該值的引用次數(shù)加1赖歌。相反枉圃,如果包含對(duì)這個(gè)值引用的變量又取得了另外一個(gè)值,則這個(gè)值得引用次數(shù)減1庐冯。當(dāng)這個(gè)值得引用次數(shù)變成0時(shí)孽亲,則說(shuō)明沒(méi)有辦法再訪問(wèn)這個(gè)值了,因而就可以將其占用的內(nèi)存空間回收回來(lái)展父。這樣返劲,當(dāng)垃圾收集器下次再運(yùn)行時(shí),它就會(huì)釋放那些引用次數(shù)為零的值所占用的內(nèi)存栖茉。
(3)性能問(wèn)題
垃圾收集的時(shí)間間隔
(4)管理內(nèi)存