javascript中内存的理解

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
posted on 2016-05-31 15:41  借个火点烟  阅读(235)  评论(0编辑  收藏  举报