关于javascript:JS-内存管理机制及验证

40次阅读

共计 2410 个字符,预计需要花费 7 分钟才能阅读完成。

作用域

JavaScript 的变量被作用域所限度,如果超出了作用域,那么变量就没有方法再被应用,这样做的长处是:

  • 能够防止以后的变量转为全局变量
  • 无效限度变量的作用区域

而变量作用域也会依照申明形式的不同,产生不同的作用域:

  • 未声明:全局变量
  • var 申明:作用域在 函数
  • letconst 申明:作用域在 {}

var 申明的变量

在函数内申明的变量其作用域会被限度在该函数的调用栈中,在内部无奈间接失去该作用域内的变量。上面的例子中,fn 函数内的变量在全局下是没有方法查看的。

function fn() {var a = 1;}
fn();
console.log(a); // 无奈失去 fn 函数內的 a 变量 

所以罕用 “ 立刻函数 ” 来限度变量的作用域,次要是防止全局变量的产生。

(function() {var b = 1;})();
console.log(b); // 无奈失去 fn 函数內的 b 变量 

let、const 申明的变量

ES6 之后所新增的 letconst 作用域则与过来不同,改用 {} 作为作限度用域的形式,这让 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

流程如下:

  1. 开拓一个内存空间来寄存变量 a,不过这时还没有赋值(起因可参考:Hoisting)

  1. a 赋值。

所有的变量都会占用内存空间,除此之外对象、数组的属性以及函数参数等也会用雷同的概念进行占用。调用一个函数时,每一个函数的作用域也都会重复的进行内存占用。随着应用程序越来越简单的状况下,如果继续的占用内存而没有进行适当的开释,那么内存可能会被耗尽。

JavaScript 引擎具备内存回收的机制,会开释不再应用的变量内存,其基本概念为:当没有任何的援用指向它时就会开释内存。

来自 MDN:collectible if there are zero references pointing to it.

内存开释的验证

上面用一个例子来阐明及验证内存开释的机制,首先用一段函数来产生一个十分长的字符串,长字符串会占用大量的内存空间。

在调用 randomString 函数后会返回一个很长的字串:

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;
}

案例一:使变量维持在可援用的状态(不会开释内存)

定义一个全局变量 demoData,这个变量会继续维持可被援用的状态。

var demoData = []; // 全局变量
function getData() {for (let i = 0; i < 1000; i++) {demoData.push(randomString(5000))
  }
}
getData()
console.log(demoData); // 可援用 demoData 值 

执行这段代码后,进入 Chrome DevTools 中的 Memory 页,这个性能能够失去以后页面所占用的内存情况。接下来点击 “Take snapshot” 按钮。

能够看到目前执行完这段代码后占用了 6.2MB 的内存空间(留神:任何浏览器环境和插件都会影响所占用的内存状态)。

案例二:使变量无奈再次被援用(执行后开释内存)

限度变量的作用域,使变量无奈再被内部援用。

此段代码仍然会执行这个函数,也会将值赋值给变量,但内部无奈再次援用 demoData 的值。

function getData() {var demoData = []; // 局部变量
  for (var i = 0; i < 1000; i++) {demoData.push(randomString(5000))
  }
}
getData();

而后回到 Memory 页点击 “Take snapshot” 从新获得内存的状态,接下来会失去与后面不同的后果,这次只占用了 1.2MB 的内存(其中 5MB 被开释掉了)

总结

通过后面的例子,咱们晓得了作用域以及内存之间的关系,而内存治理也是前端打工人必须要把握的常识(除了管制内存的应用大小,还需在必要时保留而不被开释)。


本文首发微信公众号:前端先锋

欢送扫描二维码关注公众号,每天都给你推送陈腐的前端技术文章

欢送持续浏览本专栏其它高赞文章:

  • 深刻了解 Shadow DOM v1
  • 一步步教你用 WebVR 实现虚拟现实游戏
  • 13 个帮你进步开发效率的古代 CSS 框架
  • 疾速上手 BootstrapVue
  • JavaScript 引擎是如何工作的?从调用栈到 Promise 你须要晓得的所有
  • WebSocket 实战:在 Node 和 React 之间进行实时通信
  • 对于 Git 的 20 个面试题
  • 深刻解析 Node.js 的 console.log
  • Node.js 到底是什么?
  • 30 分钟用 Node.js 构建一个 API 服务器
  • Javascript 的对象拷贝
  • 程序员 30 岁前月薪达不到 30K,该何去何从
  • 14 个最好的 JavaScript 数据可视化库
  • 8 个给前端的顶级 VS Code 扩大插件
  • Node.js 多线程齐全指南
  • 把 HTML 转成 PDF 的 4 个计划及实现

  • 更多文章 …

正文完
 0