JavaScript變量松散類型的本質(zhì)草娜,決定了它只是在特定時間用于保存特定值的一個名字而已墩剖。由于不存在定義某個變量必須要保存何種數(shù)據(jù)類型值的規(guī)則猴凹,變量的值及其數(shù)據(jù)類型可以在腳本的生命周期內(nèi)改變。
4.1基本類型和引用類型的值
ECMAScript變量可能包含兩種不同數(shù)據(jù)類型的值:基本類型指的是簡單的數(shù)據(jù)段岭皂,而引用類型指那些可能由多個值構(gòu)成的對象郊霎。
5種基本數(shù)據(jù)類型(Undefined、Null爷绘、Boolean书劝、Number、String)是按值訪問的土至,因為可以操作保存在變量中的實際的值购对。基本類型值在內(nèi)存中占據(jù)固定大小的空間陶因,因此被保存在棧內(nèi)存中骡苞。
引用類型的值是保存在內(nèi)存中的對象,JS不能直接操作對象的內(nèi)存空間楷扬,實際是在操作對象的引用而不是實際的對象解幽。
4.1.1動態(tài)的屬性
定義方式:差U那個建一個變量并為該變量賦值。
對于引用類型的值烘苹,可以為其添加屬性和方法躲株,也可以改變和刪除其屬性和方法;但不能給基本類型的值添加屬性螟加;即只能給引用類型動態(tài)地添加屬性徘溢,以便將來使用。
4.1.2復制變量值
如果從一個變量向另一個變量復制基本類型的值捆探,會在變量對象上創(chuàng)建一個新值(副本)然爆,然后把該值復制到為新變量分配的位置上。這兩個變量可以參加任何操作而不會相互影響黍图。
引用類型的值是對象曾雕,保存在堆內(nèi)存中。當從一個變量向另一個變量賦值引用類型的值時助被,同樣也會將存儲在變量對象中的值復制一份放到為新變量分配的空間中剖张。這個值的副本實際上是一個指針,指向堆內(nèi)存中的一個對象揩环。復制操作結(jié)束后搔弄,兩個變量實際上將引用同一個對象,改變其中一個變量丰滑,就會影響另一個變量顾犹。
4.1.3傳遞參數(shù)
ECMAScript中所有函數(shù)的參數(shù)都是按值傳遞的。
向參數(shù)傳遞基本類型的值時,被傳遞的值會被復制給一個局部變量(即命名參數(shù)炫刷,就是arguments對象中的一個元素)擎宝。在想?yún)?shù)傳遞引用類型的值時,會把這個值在內(nèi)存中的地址復制給一個局部變量浑玛,因此這個局部變量的變化會反映在函數(shù)的外部绍申。即使在函數(shù)內(nèi)部修改了參數(shù)的值,但原始的引用仍然保持未變顾彰。
4.1.4檢測類型
檢測基本數(shù)據(jù)類型typeof
檢測引用類型的值:
result = variable instanceof constructor
4.2執(zhí)行環(huán)境及作用域
執(zhí)行環(huán)境定義了變量或函數(shù)有權(quán)訪問的其他數(shù)據(jù)极阅,決定了它們各自的行為,決定了變量的生命周期拘央。環(huán)境中定義的所有變量和函數(shù)都保存在與之關(guān)聯(lián)的變量對象中涂屁。
全局執(zhí)行環(huán)境是最外圍的一個執(zhí)行環(huán)境。
每個函數(shù)都有自己的執(zhí)行環(huán)境灰伟。
當代碼在一個環(huán)境中執(zhí)行時會創(chuàng)建變量的一個作用域鏈拆又,用途是保證對執(zhí)行環(huán)境有權(quán)訪問的所有變量和函數(shù)的有序訪問。
內(nèi)部環(huán)境可以通過作用域鏈訪問所有的外部環(huán)境栏账,但外部環(huán)境不能訪問內(nèi)部環(huán)境中的任何變量和函數(shù)帖族。
變量的執(zhí)行環(huán)境有助于確定應該何時釋放內(nèi)存。
4.2.1延長作用域鏈
在作用域鏈的前端添加一個變量對象挡爵。
1.try-catch語句的catch塊竖般,會創(chuàng)建一個新的變量對象,其中包含的是被拋出的錯誤對象的聲明茶鹃。
2.with語句涣雕,會將指定的對象添加到作用域鏈中。
4.2.2沒有塊級作用域
1.聲明變量
使用var聲明的變量會自動被添加到最接近的環(huán)境中闭翩。如果初始化變量時沒有使用var聲明挣郭,該變量會自動被添加到全局環(huán)境。
初始化變量之前疗韵,一定要先聲明兑障。
2.查詢標識符
當為了讀取或?qū)懭攵靡粋€標識符時,必須通過搜索來確定該標識符實際代表什么蕉汪。搜索過程從作用域鏈前端開始流译,向上逐級查詢與給定名字匹配的標識符,找到則停止者疤,否則繼續(xù)沿作用域鏈向上搜索福澡;在全局環(huán)境中也沒找到這個標識符就意味著該變量尚未聲明。
4.3垃圾收集
執(zhí)行環(huán)境會負責管理代碼執(zhí)行過程中使用的內(nèi)存驹马。
垃圾收集機制的原理:找出那些不再繼續(xù)使用的變量竞漾,然后釋放其占用的內(nèi)存眯搭。垃圾收集器會按照固定時間間隔周期性執(zhí)行這一操作。離開作用域?qū)⒈蛔詣訕擞浛梢曰厥铡?br>
4.3.1標記清除
是目前主流的垃圾收集算法业岁,給當前不使用的值加上標記,然后再回收其內(nèi)存寇蚊。
垃圾收集器在運行時會給存儲在內(nèi)存中的所有變量都加上標記笔时。然后會去掉環(huán)境中的變量以及被環(huán)境中的變量引用的變量的標記。在此之后再被加上是那個標記的變量被視為準備刪除的變量仗岸,最后完成內(nèi)存清除允耿。
4.3.2引用計數(shù)
跟蹤記錄每個值被引用的次數(shù)。有個嚴重問題:循環(huán)引用會導致大量內(nèi)存得不到回收扒怖。
4.3.3性能問題
確定垃圾收集器的時間間隔较锡。
4.3.4管理內(nèi)存
分配給Web瀏覽器的可用內(nèi)存數(shù)量通常要比分配給桌面應用程序的少,目的是方式內(nèi)存耗盡導致系統(tǒng)崩潰盗痒。內(nèi)存限制會影響給變量分配內(nèi)存蚂蕴,同時還會影響調(diào)用棧以及在一個線程中能夠同時執(zhí)行的語句數(shù)量。因此確保占用最少的內(nèi)存可以讓頁面獲得更好的性能俯邓。
優(yōu)化內(nèi)存占用的最佳方式就是為執(zhí)行中的代碼只保存必要的數(shù)據(jù)骡楼。
數(shù)據(jù)不再有用則將其值設(shè)為null來釋放引用,即解除引用稽鞭。適用于大多數(shù)全局變量和全局對象屬性鸟整。應該及時解除不再使用的全局變量、全局對象屬性以及循環(huán)引用變量的引用朦蕴。