成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

JavaScript中的內(nèi)存泄漏以及如何處理

itvincent / 612人閱讀

摘要:本文將會(huì)討論中的內(nèi)存泄漏以及如何處理,方便大家在使用編碼時(shí),更好的應(yīng)對(duì)內(nèi)存泄漏帶來(lái)的問(wèn)題。當(dāng)內(nèi)存不再需要時(shí)進(jìn)行釋放大部分內(nèi)存泄漏問(wèn)題都是在這個(gè)階段產(chǎn)生的,這個(gè)階段最難的問(wèn)題就是確定何時(shí)不再需要已分配的內(nèi)存。中的相同對(duì)象稱為全局。

隨著現(xiàn)在的編程語(yǔ)言功能越來(lái)越成熟、復(fù)雜,內(nèi)存管理也容易被大家忽略。本文將會(huì)討論JavaScript中的內(nèi)存泄漏以及如何處理,方便大家在使用JavaScript編碼時(shí),更好的應(yīng)對(duì)內(nèi)存泄漏帶來(lái)的問(wèn)題。

概述

像C語(yǔ)言這樣的編程語(yǔ)言,具有簡(jiǎn)單的內(nèi)存管理功能函數(shù),例如malloc( )和free( )。開(kāi)發(fā)人員可以使用這些功能函數(shù)來(lái)顯式地分配和釋放系統(tǒng)的內(nèi)存。

當(dāng)創(chuàng)建對(duì)象和字符串等時(shí),JavaScript就會(huì)分配內(nèi)存,并在不再使用時(shí)自動(dòng)釋放內(nèi)存,這種機(jī)制被稱為垃圾收集。這種釋放資源看似是“自動(dòng)”的,但本質(zhì)是混淆的,這也給JavaScript(以及其他高級(jí)語(yǔ)言)的開(kāi)發(fā)人員產(chǎn)生了可以不關(guān)心內(nèi)存管理的錯(cuò)誤印象。其實(shí)這是一個(gè)大錯(cuò)誤。

即使使用高級(jí)語(yǔ)言,開(kāi)發(fā)人員也應(yīng)該理解內(nèi)存管理的知識(shí)。有時(shí)自動(dòng)內(nèi)存管理也會(huì)存在問(wèn)題(例如垃圾收集器中的錯(cuò)誤或?qū)嵤┫拗频龋?,開(kāi)發(fā)人員必須了解這些問(wèn)題才能正確地進(jìn)行處理。

內(nèi)存生命周期

無(wú)論你使用的是什么編程語(yǔ)言,內(nèi)存生命周期幾乎都是一樣的:

以下是對(duì)內(nèi)存生命周期中每個(gè)步驟發(fā)生的情況的概述:

分配內(nèi)存? - 內(nèi)存由操作系統(tǒng)分配,允許程序使用它。在簡(jiǎn)單的編程語(yǔ)言中,這個(gè)過(guò)程是開(kāi)發(fā)人員應(yīng)該處理的一個(gè)顯式操作。然而,在高級(jí)編程語(yǔ)言中,系統(tǒng)會(huì)幫助你完成這個(gè)操作。

內(nèi)存使用 -? 這是程序使用之前申請(qǐng)內(nèi)存的時(shí)間段,你的代碼會(huì)通過(guò)使用分配的變量來(lái)對(duì)內(nèi)存進(jìn)行讀取和寫入操作。

釋放內(nèi)存 ?- 對(duì)于不再需要的內(nèi)存進(jìn)行釋放的操作,以便確保其變成空閑狀態(tài)并且可以被再次使用。與分配內(nèi)存操作一樣,這個(gè)操作在簡(jiǎn)單的編程語(yǔ)言中是需要顯示操作的。

什么是內(nèi)存?

在硬件層面上,計(jì)算機(jī)的內(nèi)存由大量的觸發(fā)器組成的。每個(gè)觸發(fā)器包含一些晶體管,并能夠存儲(chǔ)一位數(shù)據(jù)。多帶帶的觸發(fā)器可以通過(guò)唯一的標(biāo)識(shí)符來(lái)尋址,所以我們可以讀取和覆蓋它們。因此,從概念上講,我們可以把整個(gè)計(jì)算機(jī)內(nèi)存看作是我們可以讀寫的一大塊空間。

很多東西都存儲(chǔ)在內(nèi)存中:

程序使用的所有變量和其他數(shù)據(jù)。

程序的代碼,包括操作系統(tǒng)的代碼。

編譯器和操作系統(tǒng)一起工作,來(lái)處理大部分的內(nèi)存管理,但是我們需要了解從本質(zhì)上發(fā)生了什么。

編譯代碼時(shí),編譯器會(huì)檢查原始數(shù)據(jù)類型,并提前計(jì)算它們需要多少內(nèi)存,然后將所需的內(nèi)存分配給調(diào)用堆??臻g中的程序。分配這些變量的空間被稱為堆??臻g,隨著函數(shù)的調(diào)用,內(nèi)存會(huì)被添加到現(xiàn)有的內(nèi)存之上。當(dāng)終止時(shí),空間以LIFO(后進(jìn)先出)順序被移除。例如如下聲明:

int n; // 4個(gè)字節(jié)
int x [4]; // 4個(gè)元素的數(shù)組,每一個(gè)占4個(gè)字節(jié)
double m; // 8個(gè)字節(jié)

編譯器插入與操作系統(tǒng)進(jìn)行交互的代碼,以便在堆棧中請(qǐng)求所需的字節(jié)數(shù)來(lái)存儲(chǔ)變量。

在上面的例子中,編譯器知道每個(gè)變量的確切內(nèi)存地址。實(shí)際上,每當(dāng)我們寫入這個(gè)變量n,它就會(huì)在內(nèi)部翻譯成“內(nèi)存地址4127963”。

注意,如果我們?cè)噲D訪問(wèn)x[4],我們將訪問(wèn)與m關(guān)聯(lián)的數(shù)據(jù)。這是因?yàn)槲覀冋谠L問(wèn)數(shù)組中不存在的元素 - 它比數(shù)組中最后一個(gè)數(shù)據(jù)實(shí)際分配的元素多了4個(gè)字節(jié)x[3],并且可能最終讀?。ɑ蚋采w)了一些m比特。這對(duì)其余部分會(huì)產(chǎn)生不利的后果。

當(dāng)函數(shù)調(diào)用其它函數(shù)時(shí),每個(gè)函數(shù)被調(diào)用時(shí)都會(huì)得到自己的堆棧塊。它會(huì)保留所有的局部變量和一個(gè)程序計(jì)數(shù)器,還會(huì)記錄執(zhí)行的地方。當(dāng)功能完成時(shí),其內(nèi)存塊會(huì)被釋放,可以再次用于其它目的。

動(dòng)態(tài)分配

如若我們不知道編譯時(shí),變量需要的內(nèi)存數(shù)量時(shí),事情就會(huì)變得復(fù)雜。假設(shè)我們想要做如下事項(xiàng):

int n = readInput(); //讀取用戶的輸入
...
//用“n”個(gè)元素創(chuàng)建一個(gè)數(shù)組

在編譯時(shí),編譯器不知道數(shù)組需要多少內(nèi)存,因?yàn)樗怯捎脩籼峁┑妮斎胫禌Q定的。

因此,它不能為堆棧上的變量分配空間。相反,我們的程序需要在運(yùn)行時(shí)明確地向操作系統(tǒng)請(qǐng)求適當(dāng)?shù)目臻g。這個(gè)內(nèi)存是從堆空間分配的。下表總結(jié)了靜態(tài)和動(dòng)態(tài)內(nèi)存分配之間的區(qū)別:

在JavaScript中分配內(nèi)存

現(xiàn)在來(lái)解釋如何在JavaScript中分配內(nèi)存。

JavaScript使得開(kāi)發(fā)人員免于處理內(nèi)存分配的工作。

var n = 374; // allocates memory for a number
var s = "sessionstack"; // allocates memory for a string

var o = {
  a: 1,
  b: null
}; // allocates memory for an object and its contained values

var a = [1, null, "str"];  // (like object) allocates memory for the
                           // array and its contained values

function f(a) {
  return a + 3;
} // allocates a function (which is a callable object)

// function expressions also allocate an object
someElement.addEventListener("click", function() {
  someElement.style.backgroundColor = "blue";
}, false);

一些函數(shù)調(diào)用也會(huì)導(dǎo)致對(duì)象分配:

var d = new Date(); // allocates a Date object
var e = document.createElement("div"); // allocates a DOM element

方法可以分配新的值或?qū)ο螅?/p>

var s1 = "sessionstack";
var s2 = s1.substr(0, 3); // s2 is a new string
// Since strings are immutable, 
// JavaScript may decide to not allocate memory, 
// but just store the [0, 3] range.

var a1 = ["str1", "str2"];
var a2 = ["str3", "str4"];
var a3 = a1.concat(a2); 
// new array with 4 elements being
// the concatenation of a1 and a2 elements 
在JavaScript中使用內(nèi)存

基本上在JavaScript中使用分配的內(nèi)存,意味著在其中讀寫。

這可以通過(guò)讀取或?qū)懭胱兞炕驅(qū)ο髮傩缘闹?,或者甚至將參?shù)傳遞給函數(shù)來(lái)完成。

當(dāng)內(nèi)存不再需要時(shí)進(jìn)行釋放

大部分內(nèi)存泄漏問(wèn)題都是在這個(gè)階段產(chǎn)生的,這個(gè)階段最難的問(wèn)題就是確定何時(shí)不再需要已分配的內(nèi)存。它通常需要開(kāi)發(fā)人員確定程序中的哪個(gè)部分不再需要這些內(nèi)存,并將其釋放。

高級(jí)語(yǔ)言嵌入了一個(gè)名為垃圾收集器的功能,其工作是跟蹤內(nèi)存分配和使用情況,以便在不再需要分配內(nèi)存的情況下自動(dòng)釋放內(nèi)存。

不幸的是,這個(gè)過(guò)程無(wú)法做到那么準(zhǔn)確,因?yàn)橄衲承﹥?nèi)存不再需要的問(wèn)題是不能由算法來(lái)解決的。

大多數(shù)垃圾收集器通過(guò)收集不能被訪問(wèn)的內(nèi)存來(lái)工作,例如指向它的變量超出范圍的這種情況。然而,這種方式只能收集內(nèi)存空間的近似值,因?yàn)樵趦?nèi)存的某些位置可能仍然有指向它的變量,但它卻不會(huì)被再次訪問(wèn)。

由于確定一些內(nèi)存是否“不再需要”,是不可判定的,所以垃圾收集機(jī)制就有一定的局限性。下面將解釋主要垃圾收集算法及其局限性的概念。

內(nèi)存引用

垃圾收集算法所依賴的主要概念之一就是內(nèi)存引用。

在內(nèi)存管理情況下,如果一個(gè)對(duì)象訪問(wèn)變量(可以是隱含的或顯式的),則稱該對(duì)象引用另一個(gè)對(duì)象。例如,JavaScript對(duì)象具有對(duì)其原對(duì)象(隱式引用)及其屬性值(顯式引用)的引用。

在這種情況下,“對(duì)象”的概念擴(kuò)展到比普通JavaScript對(duì)象更廣泛的范圍,并且還包含函數(shù)范圍。

引用計(jì)數(shù)垃圾收集

這是最簡(jiǎn)單的垃圾收集算法。如果有零個(gè)引用指向它,則該對(duì)象會(huì)被認(rèn)為是“垃圾收集” 。

看看下面的代碼:

var o1 = {
  o2: {
    x: 1
  }
};

// 2 objects are created. 
// "o2" is referenced by "o1" object as one of its properties.
// None can be garbage-collected


var o3 = o1; // the "o3" variable is the second thing that 
            // has a reference to the object pointed by "o1".

                                                       
o1 = 1;      // now, the object that was originally in "o1" has a         
            // single reference, embodied by the "o3" variable

var o4 = o3.o2; // reference to "o2" property of the object.
                // This object has now 2 references: one as
                // a property. 
                // The other as the "o4" variable

o3 = "374"; // The object that was originally in "o1" has now zero
            // references to it. 
            // It can be garbage-collected.
            // However, what was its "o2" property is still
            // referenced by the "o4" variable, so it cannot be
            // freed.

o4 = null; // what was the "o2" property of the object originally in
           // "o1" has zero references to it. 
           // It can be garbage collected. 
周期引起問(wèn)題

在周期方面有一個(gè)限制。例如下面的例子,創(chuàng)建兩個(gè)對(duì)象并相互引用,這樣會(huì)創(chuàng)建一個(gè)循環(huán)引用。在函數(shù)調(diào)用之后,它們將超出范圍,所以它們實(shí)際上是無(wú)用的,可以被釋放。然而,引用計(jì)數(shù)算法認(rèn)為,由于兩個(gè)對(duì)象中的每一個(gè)都被引用至少一次,所以兩者都不能被垃圾收集機(jī)制收回。

function f() {
  var o1 = {};
  var o2 = {};
  o1.p = o2; // o1 references o2
  o2.p = o1; // o2 references o1. This creates a cycle.
}

f( );
標(biāo)記和掃描算法

為了決定是否需要對(duì)象,標(biāo)記和掃描算法會(huì)確定對(duì)象是否是活動(dòng)的。

標(biāo)記和掃描算法經(jīng)過(guò)以下3個(gè)步驟:

roots:通常,root是代碼中引用的全局變量。例如,在JavaScript中,可以充當(dāng)root的全局變量是“窗口”對(duì)象。Node.js中的相同對(duì)象稱為“全局”。所有root的完整列表由垃圾收集器構(gòu)建。
然后算法會(huì)檢查所有root和他們的子對(duì)象并且標(biāo)記它們是活動(dòng)的(即它們不是垃圾)。任何root不能達(dá)到的,將被標(biāo)記為垃圾。
最后,垃圾回收器釋放所有未標(biāo)記為活動(dòng)的內(nèi)存塊,并將該內(nèi)存返回給操作系統(tǒng)。

這個(gè)算法比引用計(jì)數(shù)垃圾收集算法更好。JavaScript垃圾收集(代碼/增量/并發(fā)/并行垃圾收集)領(lǐng)域中所做的所有改進(jìn)都是對(duì)這種標(biāo)記和掃描算法的實(shí)現(xiàn)改進(jìn),但不是對(duì)垃圾收集算法本身的改進(jìn)。

周期不再是問(wèn)題了

在上面的相互引用例子中,在函數(shù)調(diào)用返回之后,兩個(gè)對(duì)象不再被全局對(duì)象可訪問(wèn)的對(duì)象引用。因此,它們將被垃圾收集器發(fā)現(xiàn),從而進(jìn)行收回。

即使在對(duì)象之間有引用,它們也不能從root目錄中訪問(wèn),從而會(huì)被認(rèn)為是垃圾而收集。

抵制垃圾收集器的直觀行為

盡管垃圾收集器使用起來(lái)很方便,但它們也有自己的一套標(biāo)準(zhǔn),其中之一是非決定論。換句話說(shuō),垃圾收集是不可預(yù)測(cè)的。你不能真正知道什么時(shí)候進(jìn)行收集,這意味著在某些情況下,程序會(huì)使用更多的內(nèi)存,雖然這是實(shí)際需要的。在其它情況下,在特別敏感的應(yīng)用程序中,短暫暫停是很可能出現(xiàn)的。盡管非確定性意味著不能確定何時(shí)進(jìn)行集合,但大多數(shù)垃圾收集實(shí)現(xiàn)了共享在分配期間進(jìn)行收集的通用模式。如果沒(méi)有執(zhí)行分配,大多數(shù)垃圾收集會(huì)保持空閑狀態(tài)。如以下情況:

大量的分配被執(zhí)行。

大多數(shù)這些元素(或所有這些元素)被標(biāo)記為無(wú)法訪問(wèn)(假設(shè)我們將一個(gè)引用指向不再需要的緩存)。

沒(méi)有進(jìn)一步的分配執(zhí)行。

在這種情況下,大多數(shù)垃圾收集不會(huì)做出任何的收集工作。換句話說(shuō),即使有不可用的引用需要收集,但是收集器不會(huì)進(jìn)行收集。雖然這并不是嚴(yán)格的泄漏,但仍會(huì)導(dǎo)致內(nèi)存使用率高于平時(shí)。

什么是內(nèi)存泄漏?

內(nèi)存泄漏是應(yīng)用程序使用過(guò)的內(nèi)存片段,在不再需要時(shí),不能返回到操作系統(tǒng)或可用內(nèi)存池中的情況。

編程語(yǔ)言有各自不同的內(nèi)存管理方式。但是是否使用某一段內(nèi)存,實(shí)際上是一個(gè)不可判定的問(wèn)題。換句話說(shuō),只有開(kāi)發(fā)人員明確的知道是否需要將一塊內(nèi)存返回給操作系統(tǒng)。

四種常見(jiàn)的JavaScript內(nèi)存泄漏

1:全局變量

JavaScript以一種有趣的方式來(lái)處理未聲明的變量:當(dāng)引用未聲明的變量時(shí),會(huì)在全局對(duì)象中創(chuàng)建一個(gè)新變量。在瀏覽器中,全局對(duì)象將是window,這意味著

function foo(arg) {
    bar = "some text";
}

相當(dāng)于:

function foo(arg) {
    window.bar = "some text";
}

bar只是foo函數(shù)中引用一個(gè)變量。如果你不使用var聲明,將會(huì)創(chuàng)建一個(gè)多余的全局變量。在上述情況下,不會(huì)造成很大的問(wèn)題。但是,如若是下面的這種情況。

你也可能不小心創(chuàng)建一個(gè)全局變量this:

function foo() {
    this.var1 = "potential accidental global";
}

// Foo called on its own, this points to the global object (window)
// rather than being undefined.
foo( );

你可以通過(guò)在JavaScript文件的開(kāi)始處添加‘use strict’;來(lái)避免這中錯(cuò)誤,這種方式將開(kāi)啟嚴(yán)格的解析JavaScript模式,從而防止意外創(chuàng)建全局變量。

意外的全局變量當(dāng)然是一個(gè)問(wèn)題。更多的時(shí)候,你的代碼會(huì)受到顯式的全局變量的影響,而這些全局變量在垃圾收集器中是無(wú)法收集的。需要特別注意用于臨時(shí)存儲(chǔ)和處理大量信息的全局變量。如果必須使用全局變量來(lái)存儲(chǔ)數(shù)據(jù),那么確保將其分配為空值,或者在完成后重新分配。

2:被遺忘的定時(shí)器或回調(diào)

下面列舉setInterval的例子,這也是經(jīng)常在JavaScript中使用。

對(duì)于提供監(jiān)視的庫(kù)和其它接受回調(diào)的工具,通常在確保所有回調(diào)的引用在其實(shí)例無(wú)法訪問(wèn)時(shí),會(huì)變成無(wú)法訪問(wèn)的狀態(tài)。但是下面的代碼卻是一個(gè)例外:

var serverData = loadData();
setInterval(function() {
    var renderer = document.getElementById("renderer");
    if(renderer) {
        renderer.innerHTML = JSON.stringify(serverData);
    }
}, 5000); //This will be executed every ~5 seconds.

上面的代碼片段顯示了使用引用節(jié)點(diǎn)或不再需要的數(shù)據(jù)的定時(shí)器的結(jié)果。

該renderer對(duì)象可能會(huì)在某些時(shí)候被替換或刪除,這會(huì)使interval處理程序封裝的塊變得冗余。如果發(fā)生這種情況,那么處理程序及其依賴項(xiàng)都不會(huì)被收集,因?yàn)閕nterval需要先停止。這一切都?xì)w結(jié)為存儲(chǔ)和處理負(fù)載數(shù)據(jù)的serverData不會(huì)被收集的原因。

當(dāng)使用監(jiān)視器時(shí),你需要確保做了一個(gè)明確的調(diào)用來(lái)刪除它們。

幸運(yùn)的是,大多數(shù)現(xiàn)代瀏覽器都會(huì)為你做這件事:即使你忘記刪除監(jiān)聽(tīng)器,當(dāng)被監(jiān)測(cè)對(duì)象變得無(wú)法訪問(wèn),它們就會(huì)自動(dòng)收集監(jiān)測(cè)處理器。這是過(guò)去的一些瀏覽器無(wú)法處理的情況(例如舊的IE6)。

看下面的例子:

var element = document.getElementById("launch-button");
var counter = 0;

function onClick(event) {
   counter++;
   element.innerHtml = "text " + counter;
}

element.addEventListener("click", onClick);

// Do stuff

element.removeEventListener("click", onClick);
element.parentNode.removeChild(element);

// Now when element goes out of scope,
// both element and onClick will be collected even in old browsers // that don"t handle cycles well.

由于現(xiàn)代瀏覽器支持垃圾回收機(jī)制,所以當(dāng)某個(gè)節(jié)點(diǎn)變的不能訪問(wèn)時(shí),你不再需要調(diào)用removeEventListener,因?yàn)槔厥諜C(jī)制會(huì)恰當(dāng)?shù)奶幚磉@些節(jié)點(diǎn)。

如果你正在使用jQueryAPI(其他庫(kù)和框架也支持這一點(diǎn)),那么也可以在節(jié)點(diǎn)不用之前刪除監(jiān)聽(tīng)器。即使應(yīng)用程序在較舊的瀏覽器版本下運(yùn)行,庫(kù)也會(huì)確保沒(méi)有內(nèi)存泄漏。

3:閉包

JavaScript開(kāi)發(fā)的一個(gè)關(guān)鍵方面是閉包。閉包是一個(gè)內(nèi)部函數(shù),可以訪問(wèn)外部(封閉)函數(shù)的變量。由于JavaScript運(yùn)行時(shí)的實(shí)現(xiàn)細(xì)節(jié),可能存在以下形式泄漏內(nèi)存:

var theThing = null;

var replaceThing = function(){

  var originalThing = theThing; 
  var unused = function(){ 
    if(originalThing)//對(duì)"originalThing"的引用
      console.log(“hi”); 
  };

  theThing = { 
    longStr:new Array(1000000).join("*"),
    someMethod:function(){ 
      console.log(“message”); 
    } 
  }; 
};

setInterval(replaceThing,1000);

一旦replaceThing被調(diào)用,theThing會(huì)獲取由一個(gè)大數(shù)組和一個(gè)新的閉包(someMethod)組成的新對(duì)象。然而,originalThing會(huì)被unused變量所持有的閉包所引用(這是theThing從以前的調(diào)用變量replaceThing)。需要記住的是,一旦在同一父作用域中為閉包創(chuàng)建了閉包的作用域,作用域就被共享了。

在這種情況下,閉包創(chuàng)建的范圍會(huì)將someMethod共享給unused。然而,unused有一個(gè)originalThing引用。即使unused從未使用過(guò),someMethod 也可以通過(guò)theThing在整個(gè)范圍之外使用replaceThing。而且someMethod通過(guò)unused共享了閉包范圍,unused必須引用originalThing以便使其它保持活躍(兩封閉之間的整個(gè)共享范圍)。這就阻止了它被收集。

所有這些都可能導(dǎo)致相當(dāng)大的內(nèi)存泄漏。當(dāng)上面的代碼片段一遍又一遍地運(yùn)行時(shí),你會(huì)看到內(nèi)存使用率的不斷上升。當(dāng)垃圾收集器運(yùn)行時(shí),其內(nèi)存大小不會(huì)縮小。這種情況會(huì)創(chuàng)建一個(gè)閉包的鏈表,并且每個(gè)閉包范圍都帶有對(duì)大數(shù)組的間接引用。

4:超出DOM引用

在某些情況下,開(kāi)發(fā)人員會(huì)在數(shù)據(jù)結(jié)構(gòu)中存儲(chǔ)DOM節(jié)點(diǎn),例如你想快速更新表格中的幾行內(nèi)容的情況。如果在字典或數(shù)組中存儲(chǔ)對(duì)每個(gè)DOM行的引用,則會(huì)有兩個(gè)對(duì)同一個(gè)DOM元素的引用:一個(gè)在DOM樹(shù)中,另一個(gè)在字典中。如果你不再需要這些行,則需要使兩個(gè)引用都無(wú)法訪問(wèn)。

var elements = {
    button: document.getElementById("button"),
    image: document.getElementById("image")
};

function doStuff() {
    elements.image.src = "http://example.com/image_name.png";
}

function removeImage() {
    // The image is a direct child of the body element.
    document.body.removeChild(document.getElementById("image"));
    // At this point, we still have a reference to #button in the
    //global elements object. In other words, the button element is
    //still in memory and cannot be collected by the GC.
}

在涉及DOM樹(shù)內(nèi)的內(nèi)部節(jié)點(diǎn)或葉節(jié)點(diǎn)時(shí),還有一個(gè)額外的因素需要考慮。如果你在代碼中保留對(duì)表格單元格(標(biāo)簽)的引用,并決定從DOM中刪除該表格,還需要保留對(duì)該特定單元格的引用,則可能會(huì)出現(xiàn)嚴(yán)重的內(nèi)存泄漏。你可能會(huì)認(rèn)為垃圾收集器會(huì)釋放除了那個(gè)單元之外的所有東西,但情況并非如此。由于單元格是表格的一個(gè)子節(jié)點(diǎn),并且子節(jié)點(diǎn)保留著對(duì)父節(jié)點(diǎn)的引用,所以對(duì)表格單元格的這種引用,會(huì)將整個(gè)表格保存在內(nèi)存中。

JavaScript 開(kāi)發(fā)工具推薦

SpreadJS 純前端表格控件是基于 HTML5 的 JavaScript 電子表格和網(wǎng)格功能控件,提供了完備的公式引擎、排序、過(guò)濾、輸入控件、數(shù)據(jù)可視化、Excel 導(dǎo)入/導(dǎo)出等功能,適用于 .NET、Java 和移動(dòng)端等各平臺(tái)在線編輯類 Excel 功能的表格程序開(kāi)發(fā)。

總結(jié)

以上內(nèi)容是對(duì)JavaScript內(nèi)存管理機(jī)制的講解,以及常見(jiàn)的四種內(nèi)存泄漏的分析。希望對(duì)JavaScript的編程人員有所幫助。

原文鏈接:https://blog.sessionstack.com...

轉(zhuǎn)載請(qǐng)注明出自:葡萄城控件

關(guān)于葡萄城

葡萄城成立于1980年,是全球最大的控件提供商,世界領(lǐng)先的企業(yè)應(yīng)用定制工具、企業(yè)報(bào)表和商業(yè)智能解決方案提供商,為超過(guò)75%的全球財(cái)富500強(qiáng)企業(yè)提供服務(wù)。葡萄城于1988年在中國(guó)設(shè)立研發(fā)中心,在全球化產(chǎn)品的研發(fā)過(guò)程中,不斷適應(yīng)中國(guó)市場(chǎng)的本地需求,并為軟件企業(yè)和各行業(yè)的信息化提供優(yōu)秀的軟件工具和咨詢服務(wù)。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/89892.html

相關(guān)文章

  • [譯]JavaScript何工作的:內(nèi)存以及何處四種常見(jiàn)的內(nèi)存泄漏

    摘要:是如何工作的內(nèi)存管理以及如何處理四種常見(jiàn)的內(nèi)存泄漏原文譯者幾個(gè)禮拜之前我們開(kāi)始一系列對(duì)于以及其本質(zhì)工作原理的深入挖掘我們認(rèn)為通過(guò)了解的構(gòu)建方式以及它們是如何共同合作的,你就能夠?qū)懗龈玫拇a以及應(yīng)用。 JavaScript是如何工作的:內(nèi)存管理以及如何處理四種常見(jiàn)的內(nèi)存泄漏 原文:How JavaScript works: memory management + how to han...

    tianren124 評(píng)論0 收藏0
  • JavaScript何工作:內(nèi)存+何處4個(gè)常見(jiàn)的內(nèi)存泄漏

    摘要:本系列的第一篇文章簡(jiǎn)單介紹了引擎運(yùn)行時(shí)間和堆棧的調(diào)用。編譯器將插入與操作系統(tǒng)交互的代碼,并申請(qǐng)存儲(chǔ)變量所需的堆棧字節(jié)數(shù)。當(dāng)函數(shù)調(diào)用其他函數(shù)時(shí),每個(gè)函數(shù)在調(diào)用堆棧時(shí)獲得自己的塊。因此,它不能為堆棧上的變量分配空間。 本系列的第一篇文章簡(jiǎn)單介紹了引擎、運(yùn)行時(shí)間和堆棧的調(diào)用。第二篇文章研究了谷歌V8 JavaScript引擎的內(nèi)部機(jī)制,并介紹了一些編寫JavaScript代碼的技巧。 在這第...

    anRui 評(píng)論0 收藏0
  • FCC 成都社區(qū)·前端周刊 第 11 期

    摘要:正式發(fā)布已正式發(fā)布,新版本重點(diǎn)關(guān)注工具鏈以及工具鏈在中的運(yùn)行速度問(wèn)題。文章內(nèi)容包括什么是內(nèi)存,內(nèi)存生命周期,中的內(nèi)存分配,內(nèi)存釋放,垃圾收集,種常見(jiàn)的內(nèi)存泄漏以及如何處理內(nèi)存泄漏的技巧。 1. Angular 6 正式發(fā)布 Angular 6.0.0 已正式發(fā)布,新版本重點(diǎn)關(guān)注工具鏈以及工具鏈在 Angular 中的運(yùn)行速度問(wèn)題。Angular v6 是統(tǒng)一整體框架、Material ...

    lentrue 評(píng)論0 收藏0
  • FCC 成都社區(qū)·前端周刊 第 11 期

    摘要:正式發(fā)布已正式發(fā)布,新版本重點(diǎn)關(guān)注工具鏈以及工具鏈在中的運(yùn)行速度問(wèn)題。文章內(nèi)容包括什么是內(nèi)存,內(nèi)存生命周期,中的內(nèi)存分配,內(nèi)存釋放,垃圾收集,種常見(jiàn)的內(nèi)存泄漏以及如何處理內(nèi)存泄漏的技巧。 1. Angular 6 正式發(fā)布 Angular 6.0.0 已正式發(fā)布,新版本重點(diǎn)關(guān)注工具鏈以及工具鏈在 Angular 中的運(yùn)行速度問(wèn)題。Angular v6 是統(tǒng)一整體框架、Material ...

    NusterCache 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<