99热99这里只有精品6国产,亚洲中文字幕在线天天更新,在线观看亚洲精品国产福利片 ,久久久久综合网
Swift
編程
Swift51.com
首頁
社區(qū)
▼
資訊
問答
分享
建議
開源代碼
Xcode下載
Swift教程
hot
登錄
注冊
當前位置:
首頁
> 分享
歡迎加入QQ討論群258996829
蘋果6袋
6
麥子學院
Javascript閉包是否會造成內(nèi)存泄漏?
發(fā)布時間:2016-11-29 16:34 回復:0 查看:2036 最后回復:2016-11-29 16:34
本文主要是和大家一起來討論下javascript的閉包會造成內(nèi)存泄漏嗎?希望通過本文的分享對大家
學習javascript
有所幫助。
在談內(nèi)存泄漏這個問題之前先看看JavaScript的垃圾收集機制,JavaScript 具有自動垃圾收集機制,就是找出那些不再繼續(xù)使用的變量,然后釋放其占用的內(nèi)存。為此,垃圾收集器會按照固定的時間間隔(或代碼執(zhí)行中預定的收集時間)。常用的的方法有兩種,即標記清楚和引用計數(shù)。
標記清除
JavaScript 中最常用的垃圾收集方式是標記清除(mark-and-sweep)。垃圾收集器在運行的時候會給存儲在內(nèi)存中的所有變量都加上標記(可以使用任何標記方式)。然后,它會去掉環(huán)境中的變量以及被環(huán)境中的變量引用的變量的標記。而在此之后再被加上標記的變量將被視為準備刪除的變量,原因是環(huán)境中的變量已經(jīng)無法訪問到這些變量了。最后,垃圾收集器完成內(nèi)存清除工作,銷毀那些帶標記的值并回收它們所占用的內(nèi)存空間。
引用計數(shù)
引用計數(shù)(reference counting)的含義是跟蹤記錄每個值被引用的次數(shù)。引用計數(shù)的含義是跟蹤記錄每個值被引用的次數(shù)。當聲明了一個變量并將一個引用類型值賦給該變量時,則這個值的引用次數(shù)就是1。如果同一個值又被賦給另一個變量,則該值的引用次數(shù)加1。相反,如果包含對這個值引用的變量又取得了另外一個值,則這個值的引用次數(shù)減1。當這個值的引用次數(shù)變成0 時,則說明沒有辦法再訪問這個值了,因而就可以將其占用的內(nèi)存空間回收回來。這樣,當垃圾收集器下次再運行時,它就會釋放那些引用次數(shù)為零的值所占用的內(nèi)存。
Netscape Navigator 3.0 是最早使用引用計數(shù)策略的瀏覽器,但很快它就遇到了一個嚴重的問題,請看下面這個例子:
function problem(){
var objectA = new Object();
var objectB = new Object();
objectA.someOtherObject = objectB;
objectB.anotherObject = objectA;
}
說明:objectA 和objectB 通過各自的屬性相互引用,即這兩個對象的引用次數(shù)都是2,在采用標記清除策略的實現(xiàn)中,由于函數(shù)執(zhí)行之后,這兩個對象都離開了作用域,因此這種相互引用不是個問題。但在采用引用計數(shù)策略的實現(xiàn)中,當函數(shù)執(zhí)行完畢后,objectA 和objectB 還說明將繼續(xù)存在,因為它們的引用次數(shù)永遠不會是0。假如這個函數(shù)被重復多次調(diào)用,就會導致大量內(nèi)存得不到回收。
為此,Netscape 在Navigator 4.0 中放棄了引用計數(shù)方式,然而引用計數(shù)導致的麻煩并未就此了結(jié)。IE9以前中有一部分對象并不是原生JavaScript 對象。例如,其BOM 和DOM 中的對象就是使用C++以COM(Component Object Model,組件對象模型)對象的形式實現(xiàn)的,而COM 對象的垃圾收集機制采用的就是引用計數(shù)策略。因此,即使IE 的JavaScript 引擎是使用標記清除策略來實現(xiàn)的,但JavaScript 訪問的COM 對象依然是基于引用計數(shù)策略的。換句話說,只要在IE 中涉及COM 對象,就會存在循環(huán)引用的問題。 比如:
var element = document.getElementById("some_element");
var myObject = new Object();
myObject.element = element;
element.someObject = myObject;
DOM 元素(element)與一個原生JavaScript 對象(myObject)之間創(chuàng)建了循環(huán)引用。其中,變量myObject 有一個名為element 的屬性指向element 對象;而變量element 也有一個屬性名叫someObject 回指myObject。由于存在這個循環(huán)引用,即使將例子中的DOM 從頁面中移除,它也永遠不會被回收。
解決辦法:將變量設為null從而切斷變量與它此前引用的值之間的連接。
myObject.element = null;
element.someObject = null;
看完上面的內(nèi)容,我來談正題。
閉包不會引起內(nèi)存泄漏
由于IE9 之前的版本對JScript 對象和COM 對象使用不同的垃圾收集。因此閉包在IE 的這些版本中會導致一些特殊的問題。具體來說,如果閉包的作用域鏈中保存著一個HTML 元素,那么就意味著該元素將無法被銷毀
請看例子:
function assignHandler(){
var element = document.getElementById("someElement");
element.onclick = function(){
alert(element.id);
};
}
以上代碼創(chuàng)建了一個作為element 元素事件處理程序的閉包,而這個閉包則又創(chuàng)建了一個循環(huán)引用(事件將在第13 章討論)。由于匿名函數(shù)保存了一個對assignHandler()的活動對象的引用,因此就會導致無法減少element 的引用數(shù)。只要匿名函數(shù)存在,element 的引用數(shù)至少也是1,因此它所占用的內(nèi)存就永遠不會被回收
解決辦法前言已經(jīng)提到過,把element.id 的一個副本保存在一個變量中,從而消除閉包中該變量的循環(huán)引用同時將element變量設為null。
function assignHandler(){
var element = document.getElementById("someElement");
var id = element.id;
element.onclick = function(){
alert(id);
};
element = null;
}
總結(jié):閉包并不會引起內(nèi)存泄漏,只是由于IE9之前的版本對JScript對象和COM對象使用不同的垃圾收集,從而導致內(nèi)存無法進行回收,這是IE的問題,所以閉包和內(nèi)存泄漏沒半毛錢關系。
來源:全棧開發(fā)者
取消引用
您還未登錄,
請先登錄
提 問
熱門帖子
iDev 全平臺開發(fā)者大會門票免費送!限量10張!
蘋果Mac Pro垃圾桶 最低配的ME253CH
本人想買個蘋果電腦搞開發(fā),哪位大俠指點下
求助:failable initializer 'init(name:)' cannot override a non-failable initializer
為慶祝Swift發(fā)布1個月,雨燕社區(qū)正式上線。
在UITextFeild里輸入數(shù)據(jù),這個數(shù)據(jù)怎么做加減乘除?
Swift 高仿喜馬拉雅FM
要成為自由職業(yè)者?先要學會蘋果的Swift哦
用swift實現(xiàn)的調(diào)用系統(tǒng)相機,相冊的DEMO
關于嵌入式引用\()
Swift 教程
最新帖子
swift_5.3可以更新了
swift如何實現(xiàn)左滑刪除
IBM Swift Sandbox訪問
Thread 18: Fatal error: 'try!' expression unexpectedly raised an error: Error
跟隨手勢滑動的ScrollableTextField
Swift5.0什么時候出
什么時候出5.0
PerfectTemplate 無法編譯
WWDC19 蘋果宣布全新 UI 框架 SwiftUI
水平滾動視圖Carousel
Xcode 9.4下載
?
Copyright © 2017 Swift 編程 版權所有
推動 Swift 成為最受歡迎的編程語言!
友鏈、商務合作:service??swift51.com
手機版