自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

JS 內(nèi)存管理機(jī)制及驗證

開發(fā) 前端
在函數(shù)內(nèi)聲明的變量其作用域會被限制在該函數(shù)的調(diào)用棧中,在外部無法直接得到該作用域內(nèi)的變量。

作用域JavaScript 的變量被作用域所限制,如果超出了作用域,那么變量就沒有辦法再被使用,這樣做的優(yōu)點是:

  • 可以避免當(dāng)前的變量轉(zhuǎn)為全局變量
  • 有效限制變量的作用區(qū)域

[[350923]]

而變量作用域也會按照聲明方式的不同,產(chǎn)生不同的作用域:

  • 未聲明:全局變量
  • var 聲明:作用域在 函數(shù) 中
  • let、const 聲明:作用域在 {} 中

var 聲明的變量

在函數(shù)內(nèi)聲明的變量其作用域會被限制在該函數(shù)的調(diào)用棧中,在外部無法直接得到該作用域內(nèi)的變量。下面的例子中, fn 函數(shù)內(nèi)的變量在全局下是沒有辦法查看的。

  1. function fn() { 
  2.   var a = 1
  3. fn(); 
  4. console.log(a); // 無法得到 fn 函數(shù)內(nèi)的 a 變量 

所以常用 "立即函數(shù)" 來限制變量的作用域,主要是避免全局變量的產(chǎn)生。

  1. (function() { 
  2.   var b = 1
  3. })(); 
  4. console.log(b); // 無法得到 fn 函數(shù)內(nèi)的 b 變量 

let、const 聲明的變量

ES6 之后所新增的let、const 作用域則與過去不同,改用 {} 作為作限制用域的方式,這讓 for 循環(huán)及部分語法避免產(chǎn)生多余的變量來影響作用域。

與 var 不同的是 const 所定義的變量作用域被限制在 {} 中。所以這個例子中的變量 c 可在外部得到值,d 則無法取到。

  1.   var c = 1
  2.   const d = 1
  3. console.log(c); // 1 
  4. console.log(d); // Uncaught ReferenceError: d is not defined,無法取到變量 d  

內(nèi)存管理機(jī)制每當(dāng)我們新增一個變量時,在內(nèi)存中就會占用一個位置來保存它的值,以便在程序后續(xù)運行時可以多次使用。

下面的代碼會在內(nèi)存中開辟一個 a 的空間來存儲數(shù)字 1 的值。

  1. var a = 1 

流程如下:

  • 開辟一個內(nèi)存空間來存放變量 a ,不過這時還沒有賦值(其原因可參考 Hoisting)
  • 為 a 賦值。

所有的變量都會占用內(nèi)存空間,除此之外對象、數(shù)組的屬性以及函數(shù)參數(shù)等也會用相同的概念進(jìn)行占用。調(diào)用一個函數(shù)時,每一個函數(shù)的作用域也都會反復(fù)的進(jìn)行內(nèi)存占用。隨著應(yīng)用程序越來越復(fù)雜的情況下,如果持續(xù)的占用內(nèi)存而沒有進(jìn)行適當(dāng)?shù)尼尫?,那么?nèi)存可能會被耗盡。

JavaScript 引擎具有內(nèi)存回收的機(jī)制,會釋放不再使用的變量內(nèi)存,其基本概念為:當(dāng)沒有任何的引用指向它時就會釋放內(nèi)存。

內(nèi)存釋放的驗證

下面用一個例子來說明及驗證內(nèi)存釋放的機(jī)制,首先用一段函數(shù)來產(chǎn)生一個非常長的字符串,長字符串會占用大量的內(nèi)存空間。

在調(diào)用 randomString 函數(shù)后會返回一個很長的字串:

  1. function randomString(length) { 
  2.   var result = ''
  3.   var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
  4.   var characterscharactersLength = characters.length; 
  5.   for (var i = 0; i < length; i++) { 
  6.     result += characters.charAt(Math.floor(Math.random() * charactersLength)); 
  7.   } 
  8.   return result; 

(1) 案例一:使變量維持在可引用的狀態(tài)(不會釋放內(nèi)存)

定義一個全局變量 demoData,這個變量會持續(xù)維持可被引用的狀態(tài)。

  1. var demoData = []; // 全局變量 
  2. function getData() { 
  3.   for (let i = 0; i < 1000; i++) { 
  4.     demoData.push(randomString(5000)) 
  5.   } 
  6. getData() 
  7. console.log(demoData); // 可引用 demoData 值 

執(zhí)行這段代碼后,進(jìn)入 Chrome DevTools 中的 Memory 頁,這個功能可以得到當(dāng)前頁面所占用的內(nèi)存狀況。接下來點擊 "Take snapshot" 按鈕。

可以看到目前執(zhí)行完這段代碼后占用了 6.2MB 的內(nèi)存空間(注意:任何瀏覽器環(huán)境和插件都會影響所占用的內(nèi)存狀態(tài))。

(2) 案例二:使變量無法再次被引用(執(zhí)行后釋放內(nèi)存)

限制變量的作用域,使變量無法再被外部引用。

此段代碼依然會執(zhí)行這個函數(shù),也會將值賦值給變量,但外部無法再次引用 demoData 的值。

  1. function getData() { 
  2.   var demoData = []; // 局部變量 
  3.   for (var i = 0; i < 1000; i++) { 
  4.     demoData.push(randomString(5000)) 
  5.   } 
  6. getData(); 

然后回到 Memory 頁點擊 "Take snapshot" 重新取得內(nèi)存的狀態(tài),接下來會得到與前面不同的結(jié)果,這次只占用了 1.2MB 的內(nèi)存(其中 5MB 被釋放掉了)

總結(jié)

通過前面的例子,我們知道了作用域以及內(nèi)存之間的關(guān)系,而內(nèi)存管理也是前端打工人必須要掌握的知識(除了控制內(nèi)存的使用大小,還需在必要時保留而不被釋放)。

 

責(zé)任編輯:趙寧寧 來源: 前端先鋒
相關(guān)推薦

2022-02-28 10:25:17

Python參數(shù)傳遞拷貝

2013-09-29 15:11:46

Linux運維內(nèi)存管理

2010-07-23 09:34:48

Python

2010-09-26 13:23:13

JVM內(nèi)存管理機(jī)制

2022-06-01 16:01:58

MySQL內(nèi)存管理系統(tǒng)

2010-12-10 15:40:58

JVM內(nèi)存管理

2011-06-29 17:20:20

Qt 內(nèi)存 QOBJECT

2016-10-09 14:41:40

Swift開發(fā)ARC

2020-08-18 19:15:44

Redis內(nèi)存管理

2019-01-23 17:08:52

Python內(nèi)存管理RealPython

2009-10-22 17:39:34

CLR內(nèi)存管理

2011-08-18 13:28:35

Objective-C內(nèi)存

2010-09-27 13:26:31

JVM內(nèi)存管理機(jī)制

2009-09-02 09:23:26

.NET內(nèi)存管理機(jī)制

2010-01-06 10:23:47

.NET Framew

2009-07-08 15:10:00

Servlet會話管理

2021-02-07 09:02:28

內(nèi)存管理length

2016-09-06 22:05:41

HttpCookieWeb

2009-09-23 17:48:00

Hibernate事務(wù)

2021-12-15 06:58:27

Go多版本管理
點贊
收藏

51CTO技術(shù)棧公眾號