最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JS前端的內(nèi)存處理的方法全面詳解

 更新時(shí)間:2023年04月11日 11:18:09   作者:Jervis_cen  
這篇文章主要為大家介紹了JS前端的內(nèi)存處理的方法全面詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

一、內(nèi)存的儲(chǔ)存和代碼執(zhí)行的場(chǎng)所關(guān)系

對(duì)于任何語(yǔ)言來(lái)說(shuō),內(nèi)存管理、垃圾回收等知識(shí)都是進(jìn)階路上繞不開(kāi)的坎。出來(lái)面試估計(jì)也沒(méi)少被問(wèn)到“前端的內(nèi)存處理你了解么? 你知道js中的垃圾處理機(jī)制嗎? 什么情況會(huì)導(dǎo)致內(nèi)存泄漏呢?

1. 儲(chǔ)存空間

兩種結(jié)構(gòu):

  • ??臻g:
  • 存儲(chǔ)原始類(lèi)型
  • 執(zhí)行上下文 (代碼空間:主要存儲(chǔ)可執(zhí)行代碼)
  • 堆空間:存儲(chǔ)引用類(lèi)型

為什么不都用棧存呢?

因?yàn)樾枰脳?lái)維護(hù)程序執(zhí)行期間上下文的狀態(tài),如果??臻g大了話,所有的數(shù)據(jù)都存放在??臻g里面,那么會(huì)影響到上下文切換的效率,進(jìn)而又影響到整個(gè)程序的執(zhí)行效率。

2. 內(nèi)存的生命周期

內(nèi)存分配:聲明變量、函數(shù)、對(duì)象的時(shí)候 內(nèi)存的使用:讀寫(xiě)內(nèi)存,使用變量 函數(shù)等 內(nèi)存回收:使用完畢,由垃圾回收機(jī)制自動(dòng)回收不再使用的內(nèi)存

3. js 中的內(nèi)存分配和使用

// 分配
const num = 123;  // 分配到棧
const str = 'sss';// 分配到棧
const obj = {};   // 分配到堆
// 使用
const a = 10;
console.log(a); // 使用

4. 調(diào)用棧下移ESP(記錄當(dāng)前執(zhí)行狀態(tài)的指針)

當(dāng)一個(gè)函數(shù)執(zhí)行結(jié)束之后,JavaScript 引擎會(huì)通過(guò)向下移動(dòng) ESP 來(lái)銷(xiāo)毀該函數(shù)保存在棧中的執(zhí)行上下文。 比方下面這個(gè)例子通過(guò)ESP 狀態(tài)來(lái)展示就如圖所示。

var foo1 = () => {
    console.log('foo1')
    foo2()
}
var foo2 = () => {
    console.log('foo2')
}
foo1()

被ESP指針移開(kāi)后的函數(shù)作用域foo1 明顯屬于不在被引用,后續(xù)將會(huì)直接被GC回收

二、 js中的垃圾回收機(jī)制

有C語(yǔ)言經(jīng)驗(yàn)的開(kāi)發(fā)者,一定明白內(nèi)存聲明分配好之后,需要手動(dòng) free 的操作,這就是手動(dòng)回收。而 Js 本身是自動(dòng)回收機(jī)制,所以開(kāi)發(fā)者不需要過(guò)多關(guān)注內(nèi)存分配和釋放的問(wèn)題。這些工作都讓 V8 引擎中的垃圾回收器(GC)給承包了。

最早接觸 js 的時(shí)候,市面上對(duì)于 js 內(nèi)存管理、垃圾回收主要講的是下面兩種概念:

1. 引用計(jì)數(shù)法

引用計(jì)數(shù)法的算法主要依賴于引用的概念,這個(gè)回收機(jī)制最早是在 IE 在使用的。目前主流瀏覽器都使用標(biāo)記清除法了??匆粋€(gè)對(duì)象是否有指向他的引用,如果沒(méi)有其他對(duì)象指向他了,說(shuō)明當(dāng)前這個(gè)對(duì)象不再被需要了。

他的缺陷在于:循環(huán)引用

如果兩個(gè)對(duì)象相互引用,盡管他們已不再被使用,但是引用計(jì)數(shù)無(wú)法識(shí)別,導(dǎo)致內(nèi)存泄漏。

2. 標(biāo)記清除法(Mark-Sweep)

將“不再使用的的對(duì)象”定義為“無(wú)法到達(dá)的對(duì)象

從根部js的全局對(duì)象觸發(fā),定時(shí)遞歸掃描內(nèi)存中的對(duì)象,凡是無(wú)法從根部到達(dá)的對(duì)象,就會(huì)被標(biāo)記為不再使用,稍后進(jìn)行回收。

執(zhí)行過(guò)程如下:

  • GC在運(yùn)行的時(shí)候會(huì)給內(nèi)存中的所有變量都加上標(biāo)記
  • 將從根部觸發(fā)能夠觸及到的對(duì)象標(biāo)記清除
  • 剩下的還有標(biāo)記的變量被視為準(zhǔn)備刪除的變量
  • GC銷(xiāo)毀帶有標(biāo)記的值 回收內(nèi)存空間

三、代際假說(shuō)和分代收集

代際假說(shuō)(The Generational Hypothesis)是現(xiàn)代瀏覽器垃圾回收策略的基礎(chǔ)。整個(gè)模型可以看看下圖

新生代(副垃圾回收器)

存放的是生存時(shí)間短、占用空間較小的的對(duì)象,通過(guò) Scavenge 算法,是把新生代空間對(duì)半劃分為兩個(gè)區(qū)域,一半是對(duì)象區(qū)域,一半是空閑區(qū)域。新的對(duì)象都要放到對(duì)象區(qū),當(dāng)快滿的時(shí)候,將還存活的對(duì)象復(fù)制到空閑區(qū)后進(jìn)行角色互換。并且執(zhí)行對(duì)象晉升策略,對(duì)象區(qū)域和空閑區(qū)域翻轉(zhuǎn)兩次還存在的對(duì)象,升級(jí)到老生代。這個(gè)復(fù)制翻轉(zhuǎn)的過(guò)程也避免內(nèi)存碎片的產(chǎn)生。

老生代(主垃圾回收器)

存放的生存時(shí)間久的對(duì)象或者大的對(duì)象,使用標(biāo)記清除的算法進(jìn)行垃圾回收。一旦執(zhí)行垃圾回收算法,都需要將正在執(zhí)行的 JavaScript 腳本暫停下來(lái),待垃圾回收完畢后再恢復(fù)腳本執(zhí)行。這種行為稱為全停頓(Stop-The-World)。實(shí)際上瀏覽器為了避免垃圾回收卡頓通過(guò)增量標(biāo)記方式將回收任務(wù)拆解成多個(gè)小任務(wù)穿插在js主線程中執(zhí)行。

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

1. 全局變量

function foo() {
    bar1 = 'aaa'; // 相當(dāng)于聲明在window.bar1
    this.bar2 = 'aaaa'
}
foo(); // 執(zhí)行函數(shù)事this指向window ,相當(dāng)于一個(gè)函數(shù)給全局變量增加了兩個(gè)變量

2. 未被清理的定時(shí)器和回調(diào)函數(shù)

//setInterval
//setTimeout
setInterval(() => {
    console.log('test')
}, 500)
//沒(méi)用用 clearInterval clearTimeout 做清除

3. 閉包

個(gè)人最喜歡《你不知道的js》里對(duì)閉包的描述

一個(gè)內(nèi)部函數(shù),有權(quán)訪問(wèn)包含其的外部函數(shù)的變量 —— 《你不知道的js》 或者也可以用“內(nèi)存逃逸”這種高逼格的屬于形容。

// 閉包 gc 案例
var one = null;
var replace = function() {
    var originalOne = one;
    var unused =function() {
        if(originalOne) {
            console.log(111);
        }
    }
    one = {
        longString: '111',
        method: function() {
            console.log()
        }
    }    
}
setInterval(replace, 500)

每次調(diào)用 replace, one 得到一個(gè)包含字符串和一個(gè)對(duì)于新閉包 method 的對(duì)象 unused 引用了 originOne

5. DOM 引用

var elements= {
    image: document.getElementById('111');
}
elements.image = null;

6. 怎么避免呢?

  • 盡量減少全局變量
//盡可能少寫(xiě)
window.object = {} // 這類(lèi)代碼
  • 使用完引用數(shù)據(jù)后,及時(shí)解除引用.null
let obj = {}
...
obj = null;
  • 避免死循環(huán)等持續(xù)執(zhí)行的操作(例如 邊界判斷不清晰的 for 或 while 循環(huán))
  • 多使用 WeakSet / WeakMap 特性
// Vue3 中就大量用了WeakMap 優(yōu)化實(shí)例引用
const bucket = new WeakMap();
...
const obj = new Proxy(data, {
  get(target, key) {
    track(target, key);
    return target[key];
  },
  set(target, key, newVal) {
    target[key] = newVal;
    trigger(target, key);
  },
});
function track(target, key) {
  if (!activeEffect) return;
  let depsMap = bucket.get(target);
  if (!depsMap) {
    bucket.set(target, (depsMap = new Map()));
  }
  // 再根據(jù)key 從 depsMap 中取得 deps, 它是一個(gè) Set 類(lèi)型,里面存儲(chǔ)著左右與當(dāng)前 key 相關(guān)聯(lián)的副作用函數(shù): effects
  let deps = depsMap.get(key);
  // 如果 deps 不存在,同樣新建一個(gè) Set 并與 key 關(guān)聯(lián)
  if (!deps) {
    depsMap.set(key, (deps = new Set()));
  }
  deps.add(activeEffect);
  activeEffect.deps.push(deps);
}
...

參考

【1】 《瀏覽器工作原理與實(shí)踐》

【2】 一文搞懂垃圾回收

以上就是JS前端的內(nèi)存處理的方法全面詳解的詳細(xì)內(nèi)容,更多關(guān)于JS前端內(nèi)存處理的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 原生js編寫(xiě)autoComplete插件

    原生js編寫(xiě)autoComplete插件

    這篇文章主要為大家詳細(xì)介紹了原生js編寫(xiě)的autoComplete插件,感興趣的小伙伴們可以參考一下
    2016-04-04
  • 微信小程序中遇到的iOS兼容性問(wèn)題小結(jié)

    微信小程序中遇到的iOS兼容性問(wèn)題小結(jié)

    這篇文章主要給大家介紹了關(guān)于微信小程序中遇到的一些iOS兼容性問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2018-11-11
  • js的Boolean對(duì)象初始值示例

    js的Boolean對(duì)象初始值示例

    Boolean(邏輯)對(duì)象用于將非邏輯值轉(zhuǎn)換為邏輯值(true 或者 false)下面為大家介紹下js的Boolean對(duì)象初始值
    2014-03-03
  • js獲取當(dāng)前年月日詳細(xì)教程(看這一篇就夠了)

    js獲取當(dāng)前年月日詳細(xì)教程(看這一篇就夠了)

    這篇文章主要給大家介紹了關(guān)于js獲取當(dāng)前年月日的相關(guān)資料,JavaScript內(nèi)置的Date對(duì)象是獲取當(dāng)前日期最常用的工具之一,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-12-12
  • 原來(lái)JS還可以這樣拆箱轉(zhuǎn)換詳解

    原來(lái)JS還可以這樣拆箱轉(zhuǎn)換詳解

    這篇文章主要給大家介紹了關(guān)于JS拆箱轉(zhuǎn)換的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-02-02
  • 詳解如何在JS代碼中消滅for循環(huán)

    詳解如何在JS代碼中消滅for循環(huán)

    這篇文章主要介紹了詳解如何在JS代碼中消滅for循環(huán),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • 點(diǎn)擊提交按鈕后按鈕變灰色不可用狀態(tài)的三種方法

    點(diǎn)擊提交按鈕后按鈕變灰色不可用狀態(tài)的三種方法

    當(dāng)點(diǎn)擊提交后,提交按鈕變灰色不可用,這樣可有效防止重復(fù)提交,本代碼就是實(shí)現(xiàn)這樣一個(gè)功能
    2013-09-09
  • JQuery入門(mén)——用one()方法綁定事件處理函數(shù)(僅觸發(fā)一次)

    JQuery入門(mén)——用one()方法綁定事件處理函數(shù)(僅觸發(fā)一次)

    one()方法功能是為所選的元素綁定一個(gè)僅觸發(fā)一次的處理函數(shù),感興趣的朋友可以了解下它的調(diào)用語(yǔ)法為:one(type, [data], fn),閱讀本文或許有意外的收獲呢
    2013-02-02
  • js中innerText/textContent和innerHTML與target和currentTarget的區(qū)別

    js中innerText/textContent和innerHTML與target和currentTarget的區(qū)別

    今天小編就為大家分享一篇關(guān)于js中innerText/textContent和innerHTML與target和currentTarget的區(qū)別,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-01-01
  • JS信息收集代碼研究(獲取客戶端的瀏覽器、cpu等軟硬件信息)

    JS信息收集代碼研究(獲取客戶端的瀏覽器、cpu等軟硬件信息)

    聽(tīng)朋友說(shuō),這段JavaScript信息收集代碼主要用于收集IP......等等什么的,用來(lái)研究,需要的朋友可以參考一下
    2023-06-06

最新評(píng)論

新田县| 景谷| 桓仁| 封丘县| 长汀县| 弥勒县| 南乐县| 易门县| 九台市| 定安县| 崇礼县| 扎鲁特旗| 疏勒县| 胶南市| 九江县| 志丹县| 云梦县| 成武县| 怀化市| 湟中县| 深水埗区| 龙泉市| 本溪市| 基隆市| 高碑店市| 汾阳市| 义马市| 尚义县| 麻城市| 蒙山县| 那坡县| 双鸭山市| 治多县| 宁化县| 兴化市| 乌拉特后旗| 崇明县| 卢龙县| 南溪县| 江山市| 土默特左旗|