這篇文章主要介紹JS內(nèi)存管理機(jī)制及驗(yàn)證的示例分析,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!
讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來自于我們對(duì)這個(gè)行業(yè)的熱愛。我們立志把好的技術(shù)通過有效、簡單的方式提供給客戶,將通過不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長期合作伙伴,公司提供的服務(wù)項(xiàng)目有:域名注冊(cè)、虛擬主機(jī)、營銷軟件、網(wǎng)站建設(shè)、竹山網(wǎng)站維護(hù)、網(wǎng)站推廣。
作用域
JavaScript 的變量被作用域所限制,如果超出了作用域,那么變量就沒有辦法再被使用,這樣做的優(yōu)點(diǎn)是:
可以避免當(dāng)前的變量轉(zhuǎn)為全局變量
有效限制變量的作用區(qū)域
而變量作用域也會(huì)按照聲明方式的不同,產(chǎn)生不同的作用域:
未聲明:全局變量
var
聲明:作用域在 函數(shù)中
let
、const
聲明:作用域在 {}
中
var 聲明的變量
在函數(shù)內(nèi)聲明的變量其作用域會(huì)被限制在該函數(shù)的調(diào)用棧中,在外部無法直接得到該作用域內(nèi)的變量。下面的例子中, fn
函數(shù)內(nèi)的變量在全局下是沒有辦法查看的。
function fn() { var a = 1; } fn(); console.log(a); // 無法得到 fn 函數(shù)內(nèi)的 a 變量
所以常用 "立即函數(shù)" 來限制變量的作用域,主要是避免全局變量的產(chǎn)生。
(function() { var b = 1; })(); console.log(b); // 無法得到 fn 函數(shù)內(nèi)的 b 變量
let、const 聲明的變量
ES6 之后所新增的let
、const
作用域則與過去不同,改用 {}
作為作限制用域的方式,這讓 for 循環(huán)及部分語法避免產(chǎn)生多余的變量來影響作用域。
與 var
不同的是 const
所定義的變量作用域被限制在 {}
中。所以這個(gè)例子中的變量 c
可在外部得到值,d
則無法取到。
{ var c = 1; const d = 1; } console.log(c); // 1 console.log(d); // Uncaught ReferenceError: d is not defined,無法取到變量 d
內(nèi)存管理機(jī)制
每當(dāng)我們新增一個(gè)變量時(shí),在內(nèi)存中就會(huì)占用一個(gè)位置來保存它的值,以便在程序后續(xù)運(yùn)行時(shí)可以多次使用。
下面的代碼會(huì)在內(nèi)存中開辟一個(gè) a
的空間來存儲(chǔ)數(shù)字 1 的值。
var a = 1
流程如下:
開辟一個(gè)內(nèi)存空間來存放變量 a
,不過這時(shí)還沒有賦值(原因可參考:Hoisting)
為 a
賦值。
所有的變量都會(huì)占用內(nèi)存空間,除此之外對(duì)象、數(shù)組的屬性以及函數(shù)參數(shù)等也會(huì)用相同的概念進(jìn)行占用。調(diào)用一個(gè)函數(shù)時(shí),每一個(gè)函數(shù)的作用域也都會(huì)反復(fù)的進(jìn)行內(nèi)存占用。隨著應(yīng)用程序越來越復(fù)雜的情況下,如果持續(xù)的占用內(nèi)存而沒有進(jìn)行適當(dāng)?shù)尼尫?,那么?nèi)存可能會(huì)被耗盡。
JavaScript 引擎具有內(nèi)存回收的機(jī)制,會(huì)釋放不再使用的變量內(nèi)存,其基本概念為:當(dāng)沒有任何的引用指向它時(shí)就會(huì)釋放內(nèi)存。
來自MDN:collectible if there are zero references pointing to it.
內(nèi)存釋放的驗(yàn)證
下面用一個(gè)例子來說明及驗(yàn)證內(nèi)存釋放的機(jī)制,首先用一段函數(shù)來產(chǎn)生一個(gè)非常長的字符串,長字符串會(huì)占用大量的內(nèi)存空間。
在調(diào)用 randomString
函數(shù)后會(huì)返回一個(gè)很長的字串:
function randomString(length) { var result = ''; var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; var charactersLength = characters.length; for (var i = 0; i < length; i++) { result += characters.charAt(Math.floor(Math.random() * charactersLength)); } return result; }
定義一個(gè)全局變量 demoData
,這個(gè)變量會(huì)持續(xù)維持可被引用的狀態(tài)。
var demoData = []; // 全局變量 function getData() { for (let i = 0; i < 1000; i++) { demoData.push(randomString(5000)) } } getData() console.log(demoData); // 可引用 demoData 值
執(zhí)行這段代碼后,進(jìn)入 Chrome DevTools 中的 Memory 頁,這個(gè)功能可以得到當(dāng)前頁面所占用的內(nèi)存狀況。接下來點(diǎn)擊 "Take snapshot" 按鈕。
可以看到目前執(zhí)行完這段代碼后占用了 6.2MB 的內(nèi)存空間(注意:任何瀏覽器環(huán)境和插件都會(huì)影響所占用的內(nèi)存狀態(tài))。
限制變量的作用域,使變量無法再被外部引用。
此段代碼依然會(huì)執(zhí)行這個(gè)函數(shù),也會(huì)將值賦值給變量,但外部無法再次引用 demoData
的值。
function getData() { var demoData = []; // 局部變量 for (var i = 0; i < 1000; i++) { demoData.push(randomString(5000)) } } getData();
然后回到 Memory 頁點(diǎn)擊 "Take snapshot" 重新取得內(nèi)存的狀態(tài),接下來會(huì)得到與前面不同的結(jié)果,這次只占用了 1.2MB 的內(nèi)存(其中 5MB 被釋放掉了)
總結(jié)
通過前面的例子,我們知道了作用域以及內(nèi)存之間的關(guān)系,而內(nèi)存管理也是前端打工人必須要掌握的知識(shí)(除了控制內(nèi)存的使用大小,還需在必要時(shí)保留而不被釋放)。
以上是“JS內(nèi)存管理機(jī)制及驗(yàn)證的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對(duì)大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!