资讯专栏INFORMATION COLUMN

高程(第四章) 变量、作用域和内存问题

xavier / 2977人阅读

摘要:不允许直接访问内存中的位置,也就是说不能直接操作对象的内存空间。在操作对象时,实际上是在操作对象的引用而不是实际的对象。解除引用的真正作用是让值脱离执行环境,以便垃圾收集器下次运行时将其回收

1 基本类型和引用类型的值

基本数据类型是按值访问的,因为可以操作保存在变量中的实际的值

基本类型值在内存中占据固定大小的空间,因此被保存在栈内存中

引用类型的值是保存在内存中的对象。JavaScript不允许直接访问内存中的位置,也就是说不能直接操作对象的内存空间。在操作对象时,实际上是在操作对象的引用而不是实际的对象。为此,引用类型的值是按引用的。

以上关于引用类型的说法不严密,当复制保存着对象的某个变量时,操作的是对象的引用。但在为对象添加属性时,操作的是实际的对象
引用类型的值是对象,保存在堆内存中

1.1 动态的属性

不能给基本类型的值添加属性,尽管这样做不会导致任何错误

1.2 复制变量值

从一个变量向另一个变量复制基本类型的值,会创建这个值的一个副本

包含引用类型值的变量实际上包含的并不是对象本身,而是一个指向该对象的指针

1.3 传递参数

ECMAScript中所有函数的参数都是按值传递的。也就是说,把函数外部的值复制给函数内部的参数,就和把值从一个变量复制到另一个变量一样

1.4 检测类型

确定一个值是哪种基本类型可以使用typeof操作符,而确定一个值是哪种引用类型可以使用instanceof操作符

console.log(typeof s);    //检测变量s是哪种基本类型值
console.log(colors instanceof Array);    //检测变量colors是否引用类型Array
2 执行环境及作用域

每个环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中。虽然我们编写的代码无法访问这个对象,但解析器在处理数据时会在后台使用它

2.1 延长作用域链

执行环境的类型总共只有两种——全局和局部(函数),但是还有其他办法来延长作用域链

以下两个语句都会在作用互联的前端添加一个变量对象:

try-catch语句的catch块

catch会创建一个新的变量对象,其中包含的是被抛出的错误对象的声明

with语句

with语句会将指定的对象添加到作用域链中

2.2 没有块级作用域

if或者for语句中定义的变量在代码块执行结束后,会存在于代码块外部的执行环境中

3 垃圾收集 3.1 标记清除

垃圾收集器在运行的时候会给储存在内存中的所有变量都加上标记(当然,可以使用任何标记方式)。然后,它会去掉环境中的变量以及被环境中的变量引用的变量的标记。而在此之后再被加上标记的变量被视为准备删除的变量,原因是环境中的变量以及无法访问到这些变量了。最后,垃圾收集器完成内存清除工作,销毁那些带标记的值并回收它们所占用的内存空间

"标记清除"是目前主流的垃圾收集算法

3.2 引用计数

引用计数的含义是跟踪记录每个值被引用的次数。当声明了一个变量并将一个引用类型值赋给该变量时,则这个值的引用次数就是1。如果同一个值又被赋给另一个值,则这个值的引用次数减1。当这个值的引用次数变成0时,则说明没有办法再访问这个值了,因而就可以将其占用的内存空间回收回来

这种引用计数策略存在一个严重的问题:循环引用

function problem(){
    var objectA = new Object();
    var objectB = new Object();
    objectA.someOtherObject = objectB;
    objectB.anotherObject = objectA;
}

上面例子中,objectA和objectB通过各自的属性互相引用,它们的引用次数永远不会是0。假如这个函数被重复多次调用,就会导致大量内存得不到回收

3.4 管理内存

一旦数据不再有用,最好通过将其值设置为null来释放其引用——这个做法叫做解除引用(dereferencing)

function createPerson(name){
    var localPerson = new Object();
    localPerson.name = name;
    return localPerson;
}
var globalPerson = createPerson("Nicholas");

globalPerson = null;    //手工解除globalPerson的引用

解除一个值得引用并不意味着自动回收该值所占用的内存。解除引用的真正作用是让值脱离执行环境,以便垃圾收集器下次运行时将其回收

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/82426.html

相关文章

  • 高程3总结#第4章变量作用域和内存问题

    摘要:当代码在一个环境中执行时,会创建变量对象的一个作用域链。作用域链的用途,是保证对执行环境有权访问的所有变量和函数的有序访问。这样,一直延续到全局执行环境全局执行环境的变量对象始终都是作用域链中的最后一个对象。 变量、作用域和内存问题 基本类型和引用类型的值 基本类型值指的是简单的数据段,而引用类型值值那些可能由多个值构成的对象。 定义基本类型值的引用和引用类型值的方法是类似的,创建...

    xumenger 评论0 收藏0
  • 《Javascript高级程序设计 (第三版)》四章 变量作用域和内存问题

    摘要:在中虽然对象通过标记清除的方式进行垃圾收,但与对象却是通过引用计数回收垃圾的,也就是说只要涉及及就会出现循环引用问题。如果垃圾收集例程回收的内存分配量低于,则变量字面量和或数组元素的临界值就会加倍。 只挑本人重要的写(有夹杂其他补充) 基本类型和引用类型的值 描述:基本类型值指的是简单的数据段,而引用类型值指那些可能由多个值构成的对象。 动态的属性 引用类型的值,我们可以为其添加属性和...

    szysky 评论0 收藏0
  • 四章 变量作用域和内存问题

    摘要:如果在局部环境没有找到该变量名,则继续沿作用域链向上搜索。很明显,访问局部变量要比访问全局变量更快,因为不用向上搜索作用域链。 按照ECMA-262定义,JavaScript的变量松散类型的本质,决定了: 它还只是在特定时间用于保存特定值的一个名字而已。 变量的值及其数据类型可以再脚本的生命周期内改变。 4.1 基本类型和引用类型的值 基本类型 简单的数据段(Undefine...

    AlphaWatch 评论0 收藏0
  • JS核心知识点梳理——上下文、作用域、闭包、this(上)

    摘要:引言满满的干货,面试必系列,参考大量资料,并集合自己的理解以及相关的面试题,对核心知识点中的作用域闭包上下文进行了梳理。如果在小区这个作用域找到了张老师,我就会在张老师的辅导下学钢琴我张老师房间钢琴构成了学琴的上下文环境。 showImg(https://segmentfault.com/img/bVbo4hv?w=1800&h=1000); 引言 满满的干货,面试必bei系列,参考大...

    Andrman 评论0 收藏0
  • JS基础知识:变量对象、作用域链和闭包

    摘要:前言这段时间一直在消化作用域链和闭包的相关知识。而作用域链则是这套规则这套规则的具体运行。是变量对象的缩写那这样放有什么好处呢我们知道作用域链保证了当前执行环境对符合访问权限的变量和函数的有序访问。 前言:这段时间一直在消化作用域链和闭包的相关知识。之前看《JS高程》和一些技术博客,对于这些概念的论述多多少少不太清楚或者不太完整,包括一些大神的技术文章。这也给我的学习上造成了一些困惑,...

    Keven 评论0 收藏0

发表评论

0条评论

xavier

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<