JavaScript的环境与内存

来源:互联网 发布:epson照片打印软件 编辑:程序博客网 时间:2024/06/14 21:16

使用具备垃圾收集机制语言编写程序,开发人员一般不必操心内存管理的问题。但是,JavaScript在进行内存管理即垃圾收集时面临的问题还是有点与众不同。其中最主要的一个问题,就是分配给Web浏览器的可用内存数量通常要比分配给桌面应用程序的少。确保占有最少的内存可以让页面获得更好的性能,而优化内存占有最佳方式,就是为执行的代码值保存必要的数据。

 

基本类型值和引用类型值

 

ECMAScript变量包含两种不同数据类型的值:基本类型值和引用类型值。基本类型值保存在栈内存中,而引用类型值保存在堆内存中。

5种基本类型Undefined、Null、Boolean、Number、String,它们的值在内存中分别占有固定大小的空间,因此可以把它们的值保存在栈内存中,也可以提高查询变量的速度,对于它们可以说是按值访问的。

如果是引用类型的值,则必须在堆内存中分配空间。因为它们的值大小不固定,因此不能保存在栈内存中,但内存地址的大小是固定的,所以可以将内存地址保存在栈内存中,再根据地址找到保存在堆中的值,这种查询方式叫做按引用访问。

 

动态属性

 

对于引用类型的值,可以为其添加属性和方法,也可以改变和删除其属性和方法,例如:

 

var myobj = new Object();

myobj.name = "obj";

alert(myobj.name);

 

但是不能给基本类型的值添加属性,例如:

 

var mystr = "string";

mystr.name = "str";

alert(mystr.name); //undefined

 

复制变量值

 

如果从一个变量向另一个变量复制基本类型的值,会在栈中创建一个新值,然后把该值复制到为新变量分配的位置上,例如:

 

var num1 = 5;

var num2 = num1;

 

如果从一个变量向另一个变量复制引用类型的值,同样会将存储在栈中的值复制一份放到为新变量分配的空间中。但是这个值的副本实际是指向存储在堆中的一个对象的指针,例如:

 

var myobj1 = new Object();

var myobj2 = myobj1;

myobj1.name = "obj";

alert(myobj2.name); //obj

 

传递参数

 

ECMAScript中所有函数参数都是按值传递的。在向参数传递基本类型的值时,被传递的值会被复制给一个局部变量,在向参数传递引用类型的值时,会把这个值在内存中的地址复制给一个局部变量。

使用基本类型值传递参数比较简单,例如:

 

function add(num) {

  num+= 10;

 return num;

}

var number = 20;

var result = add(number);

alert(number); //20

alert(result); //30

 

如果使用引用类型值则稍复杂,例如:

 

function setName(obj) {

 obj.name = "obj";

}

var myobj = new Object();

setName(myobj);

alert(myobj.name); //obj

 

但这并不表明局部作用域中修改的对象会在全局作用域中反映出来,对象仍然是按值(内存地址)传递的,例如:

 

function setName(obj) {

 obj.name = "obj";

  obj= new Object();

 obj.name = "new obj";

}

var myobj = new Object();

setName(myobj);

alert(myobj.name); //obj

 

检测类型

 

typeof操作符可以检测一个变量是哪种基本类型,但在检测引用类型时,总是返回object。通常我们并不是想知道某个值是对象,而是想知道它是什么类型的对象,可以使用instanceof操作符,语法如下:

 

result = variable instanceof constructor

 

如果变量是给定引用类型的实例,那么instanceof操作符就会返回true。根据规定,所有引用类型的值都是Object的实例。

 

环境与作用域

 

执行环境定义了变量或函数有权访问的其他数据,每个执行环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中。这个对象无法访问,但解析器会在后台使用它。全局执行环境是最外围的一个执行环境,在Web浏览器中,全局执行环境被认为是window对象。某个执行环境中的所有代码执行完毕后,该环境被销毁,保存在其中的所有变量和函数定义也随之销毁。

 

当代码在一个环境中执行时,会创建由变量对象构成的一个作用域链,保证对执行环境有权访问的所有变量和函数的有序访问。全局执行环境是作用域链中的最后一环,标识符解析是沿着作用域链一级级搜索,从作用域链接前端(当前执行环境)开始,直到找到标识符为止。

 

作用域链的延长

 

有些语句可以在作用域链的前端临时增加一个变量对象,该变量对象会在代码执行后被移除,即当执行流进入下列任何一个语句时,作用域链就会得到加长:

 

 try-cache语句的catch块。

 with语句。

 

块级作用域

 

JavaScript没有块级作用域,即花括号封闭的代码块中定义的变量可以在代码块外访问,例如:

 

if (true) {

  varcolor = "blue";

}

alert(color);

 

变量声明

 

在使用var关键字声明变量时,这个变量将被自动添加到距离最近的可用环境中。如果变量在未经声明的情况下被初始化,那么该变量会被自动添加到全局环境。

 

本文为Anyforweb技术分享博客,需要了解网站建设及更多web应用相关信息,请访问anyforweb.com。

0 0
原创粉丝点击