JavaScript中内存使用规则--堆和栈

栏目: JavaScript · 发布时间: 5年前

内容简介:堆和栈都是运行时内存中分配的一个数据区,因此也被称为堆区和栈区,但二者存储的数据类型和处理速度不同。堆(heap)用于复杂数据类型(引用类型)分配空间,例如数组对象、object对象;它是运行时动态分配内存的,因此存取速度较慢。栈(stack)中主要存放一些基本类型的变量和对象的引用,其优势是存取速度比堆要快,并且栈内的数据可以共享,但缺点是存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。栈有一个很重要的特殊性,就是存在栈中的数据可以共享。例如下面的代码定义两个变量,变量的值都是数字类型。JavaSc

堆和栈都是运行时内存中分配的一个数据区,因此也被称为堆区和栈区,但二者存储的数据类型和处理速度不同。堆(heap)用于复杂数据类型(引用类型)分配空间,例如数组对象、object对象;它是运行时动态分配内存的,因此存取速度较慢。栈(stack)中主要存放一些基本类型的变量和对象的引用,其优势是存取速度比堆要快,并且栈内的数据可以共享,但缺点是存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。

1. 栈的使用规则

栈有一个很重要的特殊性,就是存在栈中的数据可以共享。例如下面的代码定义两个变量,变量的值都是数字类型。

var a=3;
var b=3;
复制代码

JavaScript结石引起先处理 var a=3;,首先会在栈中创建一个变量为a引用,然后查找栈中是否有3这个值,如果没有找到,就将3存放进来,然后将a指向3。接着处理 var b=3;,在创建为b的引用变量后,查找栈中是否有3这个值,因为此时栈中已经存在了3,便将b直接指向3。这样,就出现了a与b同时指向3的情况。此时,如果再令a=4,那么JavaScript解释引擎会重新搜查栈中是否有4这个值,如果有,则将4存放进来,并令a指向4;如果已经有了,则直接将a指向这个地址。因此a值的改变不会影响到b的值。

2. 堆的使用规则

下面通过Array来看一下堆的行为,例如存在下面的代码:

var fruit_1="apple";
var fruit_2="orange";
var fruit_3="banana";
var oArray=[fruit_1,fruit_2,fruit_3];
var newArray=oArray;
复制代码

当创建数组时,就会在堆内存创建一个数组对象,并且在栈内存中创建一个对数组的引用。变量fruit_1、fruit_2、fruit_3为基本数据类型,它们的值直接存放在栈中;newArray、oArray为复合数据类型(引用类型),他们的引用变量存放在栈中,指向于存放在堆中的实际对象。 注意,newArray的值等于变量引用oArray,所以它也是复合数据类型(引用类型)。此时,如果更改变量fruit_1、fruit_2、fruit_3的值,那么其实是更改栈中的值;如果更改newArray或oArray的值,那么其实是更该堆中的实际对象,因此,对两个变量引用都会发生作用。例如,首先更改newArray的值,然后看oArray的值,代码如下:

alert(oArray[1]);// 返回 orange
newArray[1]="berry";
alert(oArray[1]);// 返回 berry
复制代码

同样,首现更改oArray的值,然后看newArray的值,代码如下:

alert(newArray[1]);// 返回 orange
oArray[1]='tomato';
alert(newArray[1]);// 返回 tomato
复制代码

JavaScript堆不需要程序代码来显示地释放,因为堆是由自动的垃圾回收来负责的,每种浏览器中的JavaScript解释引擎有不同的自动回收方式,但一个最基本的原则是:如果栈中不存在对堆中某个对象的引用,那么就认为该对象已经不再需要,在垃圾回收时就会清除该对象占用的内存空间。因此,在不需要时应该将对对象的引用释放掉,以利于垃圾回收,这样就可以提高程序的性能。释放对对象的引用最常用的方法就是为其赋值为null,例如下面代码将newArray赋值为null: newArray=null;

3. 易犯的错误

在堆和栈的使用问题上,最易犯的错误就是String的使用,例如下面的代码:

var str=new String('abc');
var str='abc';
复制代码

同样是创建两个字符串,第一种是用new关键字来新建String对象,对象会存放在堆中,每调用一次就会创建一个新的对象;而第二种是在栈中,栈中存放值‘abc’和对值的引用。推荐使用第二种方式创建多个'abc'字符串,这种写法在内存中只存在一个值,有利于节省内存空间。同时它可以在一定程度上提高程序的运行速度,因为存储在栈中,其值可以共享,并且由于栈访问更快,所以对于性能的提高大有裨益。而第一种方式每次都在堆中创建一个新的String对象,而不管其字符串值是否相等及是否有必要创建新对象,从而加重了程序的负担。并且堆的访问速度慢,对程序性能的影响也大。另外,出于逻辑运算的考虑,当对两个变量进行比较时,使用堆和栈存储就会有差异。下面来看一下逻辑等于和逻辑全等运算,深入理解一下堆和栈:

(1) 例如下面的代码,实际只比较栈中的值:

var str1='abc';
var str2='abc';
alert(str1==str2); // true
alert(str1===str2); // true
复制代码

不管是逻辑等于和逻辑全等运算都返回true,可以看出str1和str2指向同一个值。

(2)例如下面的代码,实际只比较堆中的值:

var str1=new String('abc');
var str2=new String('abc');
alert(str1==str2); // false
alert(str1===str2); // false
复制代码

不管是逻辑等于还是逻辑全等都返回false,可以看出str1和str2指向的不是同一个对象。

(3)例如下面的代码,比较堆和栈中的值:

var str1=new String('abc');
var str2='abc';
alert(str1==str2); // true
alert(str1===str2); // false
复制代码

在进行逻辑等于和逻辑全等运算时,会首先将变量转成相同的数据类型,然后进行对比。变量str1和str2的数据类型虽然不同,但比较运算还是返回true。但逻辑全等运算与逻辑等于运算不同,它会对数据类型进行比较,看是否是引用的同一个数据。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

编程珠玑(第二版)

编程珠玑(第二版)

[美] Jon Bentley / 谢君英、石朝江 / 中国电力出版社 / 2004-4 / 28.00元

《编程珠玑(第2版)》是计算机科学方面的经典名著。书的内容围绕程序设计人员面对的一系列实际问题展开。作者Jon Bentley 以其独有的洞察力和创造力,引导读者理解这些问题并学会解决方法,而这些正是程序员实际编程生涯中至关重要的。一起来看看 《编程珠玑(第二版)》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具