javascript中内存的理解
js中的数据类型分为基本数据类型和引用数据类型,即原始值和引用值,基本数据类型包括number、string、boolean、null、undefined;引用数据类型包括Object、Function、Array等
基本数据类型的变量名和变量值在内存中位置都为栈,是存储在栈中的简单数据类型;引用数据类型变量名存储在内存的栈中,变量值存储在堆中。对于引用数据类型,变量名只是存储在栈中的一个指针
- 栈:数据类型的大小和生存期固定,占用内存空间小,存取数度快,仅次于寄存器,主要存储基本数据类型
- 堆:数据类型的大小和生存期不固定,占用内存空间大,存取数度慢,主要存储引用数据类型
以下代码
var num = 10;
var str = "hello";
var flag = true;
var obj = new Object();
var arr = ["a","b","c"];
var person = new Person(100,"zyb",25)
function Person(id,name,age){
this.id = id;
this.name = name;
this.age = age
}
以上代码在内存中的位置分析图,以下栈中的obj指向堆中的Object,person指向第三部分,array指向第二部分
内存 |
<table>
<tr><th>栈</th></tr>
<tr><td>num:10</td></tr>
<tr><td>str:"hello"</td></tr>
<tr><td>flag:true</td></tr>
<tr><td>obj</td></tr>
<tr><td>person</td></tr>
<tr><td>array</td></tr>
</table>
<table>
<tr><th>堆</th></tr>
<tr><td>
<table>
<tr><td>Object</td></tr>
</table>
<table>
<tr><td>length:3</td></tr>
<tr><td>0:'a'</td></tr>
<tr><td>1:'b'</td></tr>
<tr><td>2:'c'</td></tr>
</table>
<table>
<tr><td>id:100</td></tr>
<tr><td>name:"zyb"</td></tr>
<tr><td>age:25</td></tr>
<tr><td>[[prototype]]</td></tr>
<tr><td>...</td></tr>
</table>
</td></tr>
</table>
</td></tr>
</table>
javascript有自己的垃圾回收机制,js解释器会自动分配和回收内存;
- 需要的时候分类配内存
- 对内存读写操作
- 不需要的时候释放内存
以下是分配内存空间的几种情况:
什么时候释放内存?
原理上一块内存不需要了,就会被释放掉,但是怎么确定一块内存不需要?一个对象不被引用就会被释放,一个对象被引用一次,引用计数就加1;
var outerObj = {//外层对象
innerObj:{//内层对象
msg:"hello"
}
}
//内层对象被外层对象引用,外层对象被outerObj引用
//内层对象引用计数:1
//外层对象引用计数:1
//内层对象和外层对象不会被垃圾回收
var tempObj = outerObj
//内层对象引用计数:1
//外层对象引用计数:2
//内层对象和外层对象不会被垃圾回收
var outerObj = 1
//内层对象引用计数:1
//外层对象引用计数:1
//内层对象和外层对象不会被垃圾回收
var _tempObj = tempObj.innerObj
//内层对象引用计数:2
//外层对象引用计数:1
//内层对象和外层对象不会被垃圾回收
var tempObj = 2
//内层对象引用计数:1
//外层对象引用计数:0
//内层对象不会被垃圾回收
//外层对象会被垃圾回收
var _tempObj = 3
//内层对象引用计数:0
//外层对象引用计数:0
//内层对象会被垃圾回收
//外层对象会被垃圾回收
引用计数缺点:
function f(){
var o = {};
var o2 = {};
o.a = o2; // o 引用 o2
o2.a = o; // o2 引用 o
return “ok”;
}
f();
分析:
上面f函数执行完后,里面的变量按理来说都会被释放,但是o和o2互相调用,二者的引用计数都不为0,因此二者都不会被收回,从而导致内存泄漏
标记清除算法
当一个对象不可达的时候,这个对象就会被释放,上面o和o2不被任何对象引用,即处于“不可达”状态,可以被回收
函数传递参数,按值传递
function box(num){ //按值传递
num+=10;
return num;
}
var num = 10;
var result = box(num);
console.log(result); //20
console.log(num); //10
执行环境及作用域
var name ="zhangsan";
function setName(){
name = "lisi"
}
setName();
console.log(name)//lisi
通过传参
var name ="zhangsan";
function setName(name){
console.log(name)//lisi
}
setName("lisi");
console.log(name)//zhangsan
|