JS 内存管理机制及验证

作者:前端小混混 来源:前端先锋
作用域JAVAScript 的变量被作用域所限制 , 如果超出了作用域 , 那么变量就没有办法再被使用 , 这样做的优点是:

  • 可以避免当前的变量转为全局变量
  • 有效限制变量的作用区域

JS 内存管理机制及验证

文章插图
 
而变量作用域也会按照声明方式的不同 , 产生不同的作用域:
  • 未声明:全局变量
  • var 声明:作用域在 函数 中
  • let、const 声明:作用域在 {} 中
var 声明的变量
在函数内声明的变量其作用域会被限制在该函数的调用栈中 , 在外部无法直接得到该作用域内的变量 。下面的例子中 ,  fn 函数内的变量在全局下是没有办法查看的 。
function fn() {
var a = 1;
}
fn();
console.log(a); // 无法得到 fn 函数內的 a 变量
所以常用 "立即函数" 来限制变量的作用域 , 主要是避免全局变量的产生 。
【JS 内存管理机制及验证】(function() {
var b = 1;
})();
console.log(b); // 无法得到 fn 函数內的 b 变量
let、const 声明的变量
ES6 之后所新增的let、const 作用域则与过去不同 , 改用 {} 作为作限制用域的方式 , 这让 for 循环及部分语法避免产生多余的变量来影响作用域 。
与 var 不同的是 const 所定义的变量作用域被限制在 {} 中 。所以这个例子中的变量 c 可在外部得到值 , d 则无法取到 。
{
var c = 1;
const d = 1;
}
console.log(c); // 1
console.log(d); // Uncaught ReferenceError: d is not defined , 无法取到变量 d
内存管理机制每当我们新增一个变量时 , 在内存中就会占用一个位置来保存它的值 , 以便在程序后续运行时可以多次使用 。
下面的代码会在内存中开辟一个 a 的空间来存储数字 1 的值 。
var a = 1
流程如下:
  • 开辟一个内存空间来存放变量 a  , 不过这时还没有赋值(其原因可参考 Hoisting)

JS 内存管理机制及验证

文章插图
 
  • 为 a 赋值 。

JS 内存管理机制及验证

文章插图
 
所有的变量都会占用内存空间 , 除此之外对象、数组的属性以及函数参数等也会用相同的概念进行占用 。调用一个函数时 , 每一个函数的作用域也都会反复地进行内存占用 。随着应用程序越来越复杂的情况下 , 如果持续的占用内存而没有进行适当的释放 , 那么内存可能会被耗尽 。
JavaScript 引擎具有内存回收的机制 , 会释放不再使用的变量内存 , 其基本概念为:当没有任何的引用指向它时就会释放内存 。
内存释放的验证
下面用一个例子来说明及验证内存释放的机制 , 首先用一段函数来产生一个非常长的字符串 , 长字符串会占用大量的内存空间 。
在调用 randomString 函数后会返回一个很长的字串:
function randomString(length) {
var result = '';
var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var characterscharactersLength = characters.length;
for (var i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
}
(1) 案例一:使变量维持在可引用的状态(不会释放内存)
定义一个全局变量 demoData , 这个变量会持续维持可被引用的状态 。
var demoData = https://www.isolves.com/it/cxkf/yy/js/2020-11-09/[]; // 全局变量
function getData() {
for (let i = 0; i < 1000; i++) {
demoData.push(randomString(5000))
}
}
getData()
console.log(demoData); // 可引用 demoData 值
执行这段代码后 , 进入 Chrome DevTools 中的 Memory 页 , 这个功能可以得到当前页面所占用的内存状况 。接下来点击 "Take snapshot" 按钮 。
JS 内存管理机制及验证

文章插图
 
可以看到目前执行完这段代码后占用了 6.2MB 的内存空间(注意:任何浏览器环境和插件都会影响所占用的内存状态) 。


推荐阅读