摘要:局部變量只在函數(shù)執(zhí)行過程中存在。此時(shí),局部變量就沒有存在的必要了,因此可以釋放他們所占的內(nèi)存以供他們使用。引用計(jì)數(shù)的含義是跟蹤記錄每個(gè)值被引用的次數(shù)。這一做法適合于大多數(shù)全局變量和局部變量的屬性。
基本類型和引用類型的值
ECMAScript變量可能包含兩種不同數(shù)據(jù)類型的值:基本類型值和引用類型值?;绢愋椭抵傅氖呛?jiǎn)單的數(shù)據(jù)段,而引用類型的值指那些可能有多個(gè)值構(gòu)成的對(duì)象。
動(dòng)態(tài)的屬性var person = new Object(); person.name = "Nicholas"; alert(person.name); // Nicholas var name = "Nicholas"; name.age = 27; alert(name.age); // undefined
這說明只能給引用類型值動(dòng)態(tài)添加屬性。
復(fù)制變量值var num1 = 5; var num2 = num1;
num1中保存的值是5.當(dāng)使用num1的值來初始化num2時(shí),num2中也保存了值5.但num2中的5與num1中的5是完全獨(dú)立的,該值只是num1中5的一個(gè)副本。
var obj1 = new Object(); var obj2 = obj1; obj1.name = "Nicholas"; alert(obj2.name); // Nicholas
變量obj1保存了一個(gè)對(duì)象的新實(shí)例。然后,這個(gè)值被復(fù)制到了obj2中;換句話說,obj1和obj2都指向同一個(gè)對(duì)象。這樣,當(dāng)為obj1添加name屬性后,可以通過obj2來訪問這個(gè)屬性。
傳遞參數(shù)function addTen(num){ num +=10; return num; } var count = 20; var result = addTen(count); alert(count); // 20, 沒有變化 alert(result); //30
例:
function setName(obj){ obj.name = "Nicholas"; } var person = new Object(); setName(person); alert(person.name); // "Nicholas"
例:
function setName(obj){ obj.name = "Nicholas"; obj = new Object(); obj.name = "Greg"; } var person = new Object(); setName(person); alert(person.name); // "Nicholas"
如果person是按引用傳遞的,那么person就會(huì)自動(dòng)被修改為指向其name屬性值為"Greg"的新對(duì)象。
執(zhí)行環(huán)境及作用域var color = "blue"; function changeColor(){ if(color == "blue"){ color = "red"; }else{ color = "blue"; } } changeColor(); alert("color is now" + color); //red垃圾收集 垃圾回收
javascript具有垃圾回收的機(jī)制,也就是說,執(zhí)行環(huán)境會(huì)負(fù)責(zé)管理代碼執(zhí)行過程中使用的內(nèi)存。其余的不多說,我們來分析一下函數(shù)中局部變量的正常生命周期。局部變量只在函數(shù)執(zhí)行過程中存在。而在這個(gè)過程中,會(huì)為局部變量在棧(或堆)內(nèi)存上分配相應(yīng)的空間,以便存儲(chǔ)他們的值。然后在函數(shù)中使用這些變量,直到函數(shù)結(jié)束。此時(shí),局部變量就沒有存在的必要了,因此可以釋放他們所占的內(nèi)存以供他們使用?,F(xiàn)在各大瀏覽器通常用采用的垃圾回收有兩種方法:標(biāo)記清除、引用計(jì)數(shù)。
標(biāo)記清除這是javascript中最常用的垃圾回收方式。當(dāng)變量進(jìn)入執(zhí)行環(huán)境是,就標(biāo)記這個(gè)變量為“進(jìn)入環(huán)境”。從邏輯上講,永遠(yuǎn)不能釋放進(jìn)入環(huán)境的變量所占用的內(nèi)存,因?yàn)橹灰獔?zhí)行流進(jìn)入相應(yīng)的環(huán)境,就可能會(huì)用到他們。當(dāng)變量離開環(huán)境時(shí),則將其標(biāo)記為“離開環(huán)境”。
垃圾收集器在運(yùn)行的時(shí)候會(huì)給存儲(chǔ)在內(nèi)存中的所有變量都加上標(biāo)記。然后,它會(huì)去掉環(huán)境中的變量以及被環(huán)境中的變量引用的標(biāo)記。而在此之后再被加上標(biāo)記的變量將被視為準(zhǔn)備刪除的變量,原因是環(huán)境中的變量已經(jīng)無法訪問到這些變量了。最后。垃圾收集器完成內(nèi)存清除工作,銷毀那些帶標(biāo)記的值,并回收他們所占用的內(nèi)存空間。
引用計(jì)數(shù)另一種不太常見的垃圾回收策略是引用計(jì)數(shù)。引用計(jì)數(shù)的含義是跟蹤記錄每個(gè)值被引用的次數(shù)。當(dāng)聲明了一個(gè)變量并將一個(gè)引用類型賦值給該變量時(shí),則這個(gè)值的引用次數(shù)就是1。相反,如果包含對(duì)這個(gè)值引用的變量又取得了另外一個(gè)值,則這個(gè)值的引用次數(shù)就減1。當(dāng)這個(gè)引用次數(shù)變成0時(shí),則說明沒有辦法再訪問這個(gè)值了,因而就可以將其所占的內(nèi)存空間給收回來。這樣,垃圾收集器下次再運(yùn)行時(shí),它就會(huì)釋放那些引用次數(shù)為0的值所占的內(nèi)存。
但是用這種方法存在著一個(gè)問題,下面來看看代碼:
function problem(){ var objA = new Object(); var objB = new Object(); objA.someOtherObject = objB; objB.anotherObject = objA; }
在這個(gè)例子中,objA和objB通過各自的屬性相互引用;也就是說這兩個(gè)對(duì)象的引用次數(shù)都是2。在采用引用計(jì)數(shù)的策略中,由于函數(shù)執(zhí)行之后,這兩個(gè)對(duì)象都離開了作用域,函數(shù)執(zhí)行完成之后,objA和objB還將會(huì)繼續(xù)存在,因?yàn)樗麄兊囊么螖?shù)永遠(yuǎn)不會(huì)是0。這樣的相互引用如果說很大量的存在就會(huì)導(dǎo)致大量的內(nèi)存泄露。
我們知道,IE中有一部分對(duì)象并不是原生JavaScript對(duì)象。例如,其BOM和DOM中的對(duì)象就是使用C++以COM(Component Object Model,組件對(duì)象)對(duì)象的形式實(shí)現(xiàn)的,而COM對(duì)象的垃圾回收器就是采用的引用計(jì)數(shù)的策略。因此,即使IE的Javascript引擎使用標(biāo)記清除的策略來實(shí)現(xiàn)的,但JavaScript訪問的COM對(duì)象依然是基于引用計(jì)數(shù)的策略的。說白了,只要IE中涉及COM對(duì)象,就會(huì)存在循環(huán)引用的問題??纯聪旅娴倪@個(gè)簡(jiǎn)單的例子:
var element = document.getElementById("some_element"); var myObj = new Object(); myObj.element = element; element.someObject = myObj;
上面這個(gè)例子中,在一個(gè)DOM元素(element)與一個(gè)原生JavaScript對(duì)象(myObj)之間建立了循環(huán)引用。其中,變量myObj有一個(gè)名為element的屬性指向element;而變量element有一個(gè)名為someObject的屬性回指到myObj。由于循環(huán)引用,即使將例子中的DOM從頁面中移除,內(nèi)存也永遠(yuǎn)不會(huì)回收。
不過上面的問題也不是不能解決,我們可以手動(dòng)切斷他們的循環(huán)引用。
myObj.element = null; element.someObject = null;內(nèi)存管理
使用JavaScript編程,我們一般都不需要管內(nèi)存回收的問題,如果說想要寫出高水平的代碼還是有點(diǎn)問題值得注意。一個(gè)主要問題就是分配給WEB瀏覽器的可用內(nèi)存通常比分配給桌面應(yīng)用程序要少。這樣做的目的主要是出自于安全方面的考慮,目的是防止運(yùn)行JavaScript的網(wǎng)頁耗盡全部系統(tǒng)內(nèi)存導(dǎo)致系統(tǒng)崩潰。內(nèi)存限制問題不僅會(huì)影響給變量分配內(nèi)存,同時(shí)還會(huì)影響調(diào)用棧以及在一個(gè)線程中能夠同時(shí)執(zhí)行的語句的數(shù)量。
因此,確保占用最少的內(nèi)存可以讓頁面獲得更好的性能。而優(yōu)化內(nèi)存占用的最佳方式,就是執(zhí)行中的代碼只保存必要的數(shù)據(jù)。一旦數(shù)據(jù)不在有用,最好通過將其值設(shè)置為null來釋放其引用——這個(gè)做法叫解除引用。這一做法適合于大多數(shù)全局變量和局部變量的屬性。局部變量會(huì)在他們離開執(zhí)行環(huán)境的時(shí)候自動(dòng)被解除引用,下面來看看代碼:
function createPerson(name){ var localPerson = new Object(); localPerson.name = name; return localPerson; } var globalPerson = createPerson("Tracy"); globalPerson = null; //手工解除引用
在這個(gè)例子中,變量globalPerson取得了createPerson()函數(shù)的返回值。在createPerson()函數(shù)內(nèi)部,我們創(chuàng)建了一個(gè)對(duì)象并將其值賦給局部變量localPerson,然后又為局部變量添加了一個(gè)名為name 的屬性。最后,當(dāng)調(diào)用這個(gè)函數(shù)的時(shí)候,localPerson以函數(shù)值的形式返回并賦值給globalPerson。由于localPerson在createPerson()函數(shù)執(zhí)行完畢后就離開了執(zhí)行環(huán)境,因此無需我們顯示地去為他們解除引用。但是對(duì)于globalPerson而言,則需要我們不使用它的時(shí)候手動(dòng)為他解除引用。
不過,解除一個(gè)值的引用并不意味著自動(dòng)回收該值所占的內(nèi)存。解除引用的真正作用是讓值脫離執(zhí)行環(huán)境,以便垃圾收集器下次運(yùn)行時(shí)將其回收。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/87583.html
摘要:執(zhí)行環(huán)境的類型有兩種全局全局執(zhí)行環(huán)境局部函數(shù)執(zhí)行環(huán)境每個(gè)環(huán)境都可以向上搜索作用域鏈,以查詢變量和函數(shù)名但任何環(huán)境都不能通過向下搜索作用域鏈而進(jìn)入另一個(gè)執(zhí)行環(huán)境。內(nèi)部可通過作用域鏈訪問外部,外部不能訪問內(nèi)部。 變量、作用域和內(nèi)存問題 ECMAScript 數(shù)據(jù)類型 基本類型(5種): Undefined,Null,Boolean,Number,String typeof() 檢測(cè)...
摘要:具體說就是執(zhí)行流進(jìn)入下列任何一個(gè)語句時(shí),作用域鏈就會(huì)得到加長(zhǎng)語句的塊。如果局部環(huán)境中存在著同名的標(biāo)識(shí)符,就不會(huì)使用位于父環(huán)境中的標(biāo)識(shí)符訪問局部變量要比訪問全局變量更快,因?yàn)椴挥孟蛏纤阉髯饔糜蜴湣? 基本類型和引用類型的值 ECMAscript變量包含 基本類型值和引用類型值 基本類型值值的是基本數(shù)據(jù)類型:Undefined, Null, Boolean, Number, String ...
摘要:在操作對(duì)象時(shí),實(shí)際上是在操作對(duì)象的引用而不是實(shí)際的對(duì)象。為此,引用類型的值是按引用訪問的。標(biāo)記清除是目前主流的垃圾收集算法,這種算法的思想是給當(dāng)前不使用的值加上標(biāo)記,然后再回收其內(nèi)存 1.在操作對(duì)象時(shí),實(shí)際上是在操作對(duì)象的引用而不是實(shí)際的對(duì)象。為此,引用類型的值是按引用訪問的。 2.當(dāng)從一個(gè)變量向另一個(gè)變量復(fù)制引用類型的值時(shí),兩個(gè)變量實(shí)際上將引用同一個(gè)對(duì)象,因此,改變其中一個(gè)變量,就會(huì)...
摘要:作用域鏈中的下一個(gè)變量對(duì)象來自包含外部環(huán)境,而再下一個(gè)變量對(duì)象則來自下一個(gè)包含環(huán)境。這樣,一直延續(xù)到全局執(zhí)行環(huán)境全局執(zhí)行環(huán)境的變量對(duì)象始終都是作用域鏈中的最后一個(gè)對(duì)象標(biāo)識(shí)符解析沿作用域鏈一級(jí)一級(jí)搜索標(biāo)識(shí)符。 一、寫在前面 最近研究了創(chuàng)建Android虛擬機(jī)、vscode結(jié)合weex開發(fā)Android APP、Vmware裝MAC虛擬機(jī)的事,看的內(nèi)容不夠多,接下來加油 二、變量、作用域和...
摘要:在中雖然對(duì)象通過標(biāo)記清除的方式進(jìn)行垃圾收,但與對(duì)象卻是通過引用計(jì)數(shù)回收垃圾的,也就是說只要涉及及就會(huì)出現(xiàn)循環(huán)引用問題。如果垃圾收集例程回收的內(nèi)存分配量低于,則變量字面量和或數(shù)組元素的臨界值就會(huì)加倍。 只挑本人重要的寫(有夾雜其他補(bǔ)充) 基本類型和引用類型的值 描述:基本類型值指的是簡(jiǎn)單的數(shù)據(jù)段,而引用類型值指那些可能由多個(gè)值構(gòu)成的對(duì)象。 動(dòng)態(tài)的屬性 引用類型的值,我們可以為其添加屬性和...
閱讀 2902·2021-11-18 10:02
閱讀 3773·2021-11-15 17:59
閱讀 2375·2021-09-06 15:00
閱讀 3411·2019-08-29 16:58
閱讀 1131·2019-08-26 10:34
閱讀 1656·2019-08-26 10:15
閱讀 1363·2019-08-26 10:11
閱讀 2793·2019-08-23 18:33