JavaScript的内存机制浅谈
一、简述
Java与JavaScript均是编程语言,强类型与弱类型(渐进式与非渐进式),根据编程语言之间的差异,那么他们的内存机制自然存在则一定的差异.
本章博客主要想与各位开发者(DL)们一起探讨关于JavaScript这门编程语言的内存机制,嘿嘿.
讨论主题: JavaScript的局部变量被内存回收问题 (基于有比较强的内存空间感)
博主:在讨论中被喷,在被喷中成长的人 (题外话)
二、内存机制
JavaScript的内存机制:内存基元(基元:相当与单位内存空间) 在变量创建时自动分配,当变量不被使用时,则被视为"垃圾"自动回收。"垃圾"被谁回收了呢? JavaScript的垃圾回收线程,采用变量标记算法及根据闭包原理进行回收,
基于讨论的主题是JavaScript的局部变量回收问题,引出3个问题:
(1) JavaScript全局变量与局部变量的生命周期;
(2) JavaScript变量在何时会被垃圾回收线程回收;
(3) JavaScript的基本数据类型与引用数据类型有哪些,何时被回收呢?
JavaScript内存模型图(注:非原型内存模型,可浏览参考博客中的文章获取知识源泉):
在进行图解之前,先灌输一波概念:JavaScript的基本数据类型及引用数据类型有哪些的问题。
基本数据类型:Number (数值) String(字符串) Null (空值) Undefined(未定义) Boolean(布尔,真假类型)
引用数据类型: Array(数组) Object(对象) 等等自定义对象.
总结:非引用的数据类型就是基本数据类型...
图解1:内存模型中,JavaScript的内存分为堆、栈、池(一般归为栈) -->与Java的内存模型不太相同,但是主体是雷同的。
基本数据类型的变量创建均在栈内存中,只是针对于基本数据类型。(对象的属性中有基本数据类型,而他们在堆内存)
<script type="text/javascript">
//页面加载完成后,回掉该函数.
$(document).ready(function(){
var varible1 = 10; //值类型
var varible2 = "Xiao Ming"; //字符串
var varible3 = null; //空值
var varible4 = true; //布尔
console.log(typeof(varible1));//number
console.log(typeof(varible2));//string
console.log(typeof(varible3));//object
console.log(typeof(varible4));//boolean
console.log(typeof(varible5));//undefined
});
</script>
图解2: 基本数据类型基本都是值传递,而引用类型当然设计为引用传递了. (引用传递与值传递自行脑部或参考其他博客)
三、内存回收
问题1:JavaScript的全局变量与局部变量的生命周期。
(1)全局变量与局部变量生命周期
全局变量当声明时,并一致作用于文档中,直到文档被浏览器"卸载"后,才被垃圾回收线程标记为可回收部分。
局部变量当声明时,只作用与该方法、函数中,该方法执行完毕后,引用变量被标记为可回收部分,等待垃圾回收线程 来回收。(重点:当该函数中存在回掉函数时,且回调函数引用该变量时,则该变量不会被标记为可回收部分.)
(这也就造成了,回调函数引用的局部变量假装成为了全局变量的问题...) ****
(请各位看官,多多指点,是否真如我所说的! 如果是真的,麻烦评论回复一下,谢谢各位大佬)
问题2:JavaScript的变量何时被垃圾回收器回收呢? (已简略的在问题一中回答.)
四、内存机制小结
小结部分:主要用于验证上述所说的正确性,采用(逻辑+代码+结果)的方式来验证.
验证问题1:JavaScript的全局变量与局部变量的生命周期问题.
逻辑:如果是全局变量,且文档不被卸载的情况下,在全局访问变量声明后的任何一个函数或方法均可以访问到;
反之,则后面的函数均访问不到
代码:
<script type="text/javascript">
//1.定义全局变量;
var global_varible = "我是全局变量";
//2.定义函数.
function testFun(){
var part_varible = "我是局部变量"
console.log(global_varible);
}
$(function(){
//如果控制台输出:我是全局变量,则说明全局生命周期正确.
testFun();
//如果控制台输出:我是局部变量,则说明局部声明周期错误,反之,则正确.
console.log(part_varible);
});
</script>
结果: 正常输出,不做贴图操作...(注:暂时不验证,局部变量在回调函数中处于一个假的全局变量问题)
局部变量处于假的全局变量问题验证设计如下:
1.$(document).ready(function(){
//1.声明该变量,并定义为null
//2.为某个元素1动态绑定点击事件,回调函数修改该变量
//3.继续为另外一个元素2动态绑定点击事件,回调函数输出该变量;
// 操作流程:首先,如果点击元素2,返回的是null,且 点击元素1再点击元素2返回的是修改的值,说明理论验证成功.
//验证逻辑:如果点击元素2,输出是null,说明:该引用变量已经被回调函数引用,此时且已经引用完了,应该被回收且标 记,那么再点击元素1后点击元素2,此时:应该还是null,说明局部变量在该函数执行结束后,直接释放了内存空间。
//反之,如果点击元素1,再点击元素2,输出的是修改的值,那么说明局部变量已经变成了所谓的假全局变量,且一直被引用下去。
(除非元素1、元素2移除绑定事件外,那么该假全局变量就变成了真局部变量被回收了)
});
注:以上结论均来源于开发过程中,所思考的问题!
参考博客:https://www.cnblogs.com/yangmin86/p/7090882.html
https://www.cnblogs.com/sachen/p/6659680.html (内存模型图)
https://blog.csdn.net/feiying008/article/details/52840944 (原型内存模型详解)