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

資訊專欄INFORMATION COLUMN

[摘譯]js內(nèi)存泄漏常見(jiàn)的四種情況

Moxmi / 2211人閱讀

摘要:本文主要選取了這篇文章中的一小部分來(lái)說(shuō)明一下中產(chǎn)生內(nèi)存泄漏的常見(jiàn)情況對(duì)于較難理解的第四種情況參考了一些文章來(lái)進(jìn)行說(shuō)明意外的全局變量中如果不用聲明變量該變量將被視為對(duì)象全局對(duì)象的屬性也就是全局變量上面的函數(shù)等價(jià)于所以你調(diào)用完了函數(shù)以后變量仍然

本文主要選取了4 Types of Memory Leaks in JavaScript and How to Get Rid Of Them 這篇文章中的一小部分來(lái)說(shuō)明一下js中產(chǎn)生內(nèi)存泄漏的常見(jiàn)情況. 對(duì)于較難理解的第四種情況, 參考了一些文章來(lái)進(jìn)行說(shuō)明.

意外的全局變量

js中如果不用var聲明變量,該變量將被視為window對(duì)象(全局對(duì)象)的屬性,也就是全局變量.

function foo(arg) {
    bar = "this is a hidden global variable";
}

// 上面的函數(shù)等價(jià)于
function foo(arg) {
    window.bar = "this is an explicit global variable";
}

所以,你調(diào)用完了函數(shù)以后,變量仍然存在,導(dǎo)致泄漏.

如果不注意this的話,還可能會(huì)這么漏:

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

// 沒(méi)有對(duì)象調(diào)用foo, 也沒(méi)有給它綁定this, 所以this是window
foo();

你可以通過(guò)加上"use strict"啟用嚴(yán)格模式來(lái)避免這類問(wèn)題, 嚴(yán)格模式會(huì)組織你創(chuàng)建意外的全局變量.

被遺忘的定時(shí)器或者回調(diào)
var someResource = getData();
setInterval(function() {
    var node = document.getElementById("Node");
    if(node) {
        node.innerHTML = JSON.stringify(someResource));
    }
}, 1000);

這樣的代碼很常見(jiàn), 如果idNode的元素從DOM中移除, 該定時(shí)器仍會(huì)存在, 同時(shí), 因?yàn)榛卣{(diào)函數(shù)中包含對(duì)someResource的引用, 定時(shí)器外面的someResource也不會(huì)被釋放.

沒(méi)有清理的DOM元素引用
var elements = {
    button: document.getElementById("button"),
    image: document.getElementById("image"),
    text: document.getElementById("text")
};

function doStuff() {
    image.src = "http://some.url/image";
    button.click();
    console.log(text.innerHTML);
}

function removeButton() {
    document.body.removeChild(document.getElementById("button"));
    
    // 雖然我們用removeChild移除了button, 但是還在elements對(duì)象里保存著#button的引用
    // 換言之, DOM元素還在內(nèi)存里面.
}
閉包

先看這樣一段代碼:

var theThing = null;
var replaceThing = function () {
  var someMessage = "123"
  theThing = {
    someMethod: function () {
      console.log(someMessage);
    }
  };
};

調(diào)用replaceThing之后, 調(diào)用theThing.someMethod, 會(huì)輸出123, 基本的閉包, 我想到這里應(yīng)該不難理解.

解釋一下的話, theThing包含一個(gè)someMethod方法, 該方法引用了函數(shù)中的someMessage變量, 所以函數(shù)中的someMessage變量不會(huì)被回收, 調(diào)用someMethod可以拿到它正確的console.log出來(lái).

接下來(lái)我這么改一下:

var theThing = null;
var replaceThing = function () {
  var originalThing = theThing;
  var someMessage = "123"
  theThing = {
    longStr: new Array(1000000).join("*"),        // 大概占用1MB內(nèi)存
    someMethod: function () {
      console.log(someMessage);
    }
  };
};

我們先做一個(gè)假設(shè), 如果函數(shù)中所有的私有變量, 不管someMethod用不用, 都被放進(jìn)閉包的話, 那么會(huì)發(fā)生什么呢.

第一次調(diào)用replaceThing, 閉包中包含originalThing = nullsomeMessage = "123", 我們?cè)O(shè)函數(shù)結(jié)束時(shí), theThing的值為theThing_1.

第二次調(diào)用replaceThing, 如果我們的假設(shè)成立, originalThing = theThing_1someMessage = "123".我們?cè)O(shè)第二次調(diào)用函數(shù)結(jié)束時(shí), theThing的值為theThing_2.注意, 此時(shí)的originalThing保存著theThing_1, theThing_1包含著和theThing_2截然不同的someMethod, theThing_1someMethod中包含一個(gè)someMessage, 同樣如果我們的假設(shè)成立, 第一次的originalThing = null應(yīng)該也在.

所以, 如果我們的假設(shè)成立, 第二次調(diào)用以后, 內(nèi)存中有theThing_1theThing_2, 因?yàn)樗麄兌际强?b>longStr把占用內(nèi)存撐起來(lái), 所以第二次調(diào)用以后, 內(nèi)存消耗比第一次多1MB.

如果你親自試了(使用Chrome的Profiles查看每次調(diào)用后的內(nèi)存快照), 會(huì)發(fā)現(xiàn)我們的假設(shè)是不成立的, 瀏覽器很聰明, 它只會(huì)把someMethod用到的變量保存下來(lái), 用不到的就不保存了, 這為我們節(jié)省了內(nèi)存.

但如果我們這么寫(xiě):

var theThing = null;
var replaceThing = function () {
  var originalThing = theThing;
  var unused = function () {
    if (originalThing)
      console.log("hi");
  };
  var someMessage = "123"
  theThing = {
    longStr: new Array(1000000).join("*"),
    someMethod: function () {
      console.log(someMessage);
    }
  };
};

unused這個(gè)函數(shù)我們沒(méi)有用到, 但是它用了originalThing變量, 接下來(lái), 如果你一次次調(diào)用replaceThing, 你會(huì)看到內(nèi)存1MB 1MB的漲.

也就是說(shuō), 雖然我們沒(méi)有使用unused, 但是因?yàn)樗褂昧?b>originalThing, 使得它也被放進(jìn)閉包了, 內(nèi)存漏了.

強(qiáng)烈建議讀者親自試試在這幾種情況下產(chǎn)生的內(nèi)存變化.

這種情況產(chǎn)生的原因, 通俗講, 是因?yàn)闊o(wú)論someMethod還是unused, 他們其中所需要用到的在replaceThing中定義的變量是保存在一起的, 所以就漏了.

如果我沒(méi)有說(shuō)明第四種情況, 可以參考以下鏈接, 或是在評(píng)論區(qū)評(píng)論.

參考鏈接

An interesting kind of JavaScript memory leak

一個(gè)意想不到的Javascript內(nèi)存泄漏

Grokking V8 closures for fun (and profit?)

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

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

相關(guān)文章

  • 金三銀四,2019大廠Android高級(jí)工程師面試題整理

    摘要:原文地址游客前言金三銀四,很多同學(xué)心里大概都準(zhǔn)備著年后找工作或者跳槽。最近有很多同學(xué)都在交流群里求大廠面試題。 最近整理了一波面試題,包括安卓JAVA方面的,目前大廠還是以安卓源碼,算法,以及數(shù)據(jù)結(jié)構(gòu)為主,有一些中小型公司也會(huì)問(wèn)到混合開(kāi)發(fā)的知識(shí),至于我為什么傾向于混合開(kāi)發(fā),我的一句話就是走上編程之路,將來(lái)你要學(xué)不僅僅是這些,豐富自己方能與世接軌,做好全棧的裝備。 原文地址:游客kutd...

    tracymac7 評(píng)論0 收藏0
  • JavaScript中的內(nèi)存泄漏以及如何處理

    摘要:本文將會(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...

    itvincent 評(píng)論0 收藏0
  • Android內(nèi)存泄漏定位、分析、解決全方案

    摘要:如果這個(gè)靜態(tài)變量在生命周期結(jié)束后沒(méi)有清空,就導(dǎo)致內(nèi)存泄漏。因此造成內(nèi)存泄露。注冊(cè)沒(méi)取消造成的內(nèi)存泄露這種的內(nèi)存泄露比純的內(nèi)存泄漏還要嚴(yán)重,因?yàn)槠渌恍┏绦蚩赡芤孟到y(tǒng)的程序的對(duì)象比如注冊(cè)機(jī)制。 原文鏈接 更多教程 為什么會(huì)發(fā)生內(nèi)存泄漏 內(nèi)存空間使用完畢之后未回收, 會(huì)導(dǎo)致內(nèi)存泄漏。有人會(huì)問(wèn):Java不是有垃圾自動(dòng)回收機(jī)制么?不幸的是,在Java中仍存在很多容易導(dǎo)致內(nèi)存泄漏的邏輯(...

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

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

0條評(píng)論

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