美文网首页我爱编程
【JS第13期】变量、作用域、内存等问题

【JS第13期】变量、作用域、内存等问题

作者: 前端刊物 | 来源:发表于2018-04-17 13:57 被阅读0次

    基本类型和引用类型

    基本类型

    • 基本类型:String、Number、Boolean、undefined、null、symbol(es6)
    • 基本类型指的是简短的数据段,固定的空间大小,因此存储在栈中
    • 可以通过 typeof 判断基本类型
    • 从一个变量向另一个变量赋值时,实际上创建了一个副本

    引用类型

    • 引用类型: Object
    • 引用类型指那些可能由多个值构成的对象,保存在堆中
    • 包含引用类型的变量实际上并不是对象本身,而是该对象的指针
    • 从一个变量向另一个变量赋值时,实际上复制的时指针,因此,两个不同变量都指向的同一个对象,我们通过一个变量修改对象,另一个变量的值也会改变
    • 可以通过 instanceof 判断对象是哪种引用类型(大致包括:Object、Function、Array、RegExp)
    • 所有的引用类型都是对象 如下
    // 函数
    fun instanceof Object // true
    // 数组
    arr instanceof Object // true
    // 正则
    reg instanceof Object // true
    // 对象
    obj instanceof Object // true
    

    执行环境及作用域

    执行环境(也称作用域)定义了变量或函数有权访问的其它数据,决定了它们各自的行为。每个执行环境都有与之相关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中。虽然我们无法访问这个对象,但解析器在处理数据时会在后台使用它

    • 执行环境有全局执行环境、函数执行环境和块级作用域(es6)
    • 每次进入一个执行环境都会创建一个用于搜索变量和函数的作用域链
    • 函数执行环境除了可以访问当前作用域的变量及函数外,还可以访问它的父级、全局等变量及函数(可以说当前函数执行环境之上的整个作用域链)
    • 全局环境只能访问在全局定义的变量和函数

    内存垃圾收集

    js具有自动垃圾收集机制,也就是说,执行环境负责管理代码执行过程的内存。而在c或c++等语言中,需要开发人员自行处理内存

    前面已经说到了,我们定义的变量、函数、对象等都是存储在栈或堆中,栈或堆其实就是在内存中分配的一部分空间。这些只有在执行阶段才会被使用,当执行完后,已经没有用了,所以,我们可以将这些占用的内存进行清理。一般实现垃圾收集的方案有2种:

    标记清除

    标记清除的原理是在运行时候会给存储在内存中的所有变量都加上标记。然后,它会去掉环境中的变量以及被环境中的变量引用的变量标记。而在此之后再被加上标记的变量则被视为准备删除的变量,然后通过那些标记进行内存清理工作。目前的浏览器已基本上使用的是标记清除。

    引用计数

    引用计数的原理是跟踪记录每一个变量值的引用次数,当声明一个变量并将值赋给该变量时,则这个引用次数加1;相反,如果该变量的值又取得了另一个值(重新赋值),则减1;当这个值的引用次数为0时,则该值没有再被使用,这样,当垃圾收集器下次运行时,就会释放那些引用次数为0的值所占的内存空间。目前,浏览器已基本上不用这种方式了,因为:循环引用同一个对象时,该值的引用次数不会为0,也就不会被清除,会导致严重的性能问题

    ie中bom和dom中的对象就是使用c++以com(组件对象模型)对象的形式实现的,而com对象的垃圾回收机制采用的正是引用计数。因此,只要在ie中涉及到com对象,就会存在循环引用的问题。

    为了解决这个问题,我们可以手动的将变量在不再使用的时候设置为null

    ie9以上的浏览器通过将bom和dom对象转换称js对象来避免两种垃圾收集算法并存导致的问题,也清除了常见的内存泄露现象

    性能问题

    ie垃圾收集器是一个脚本中包含的变量超过默认的临界点时,会被触发垃圾回收机制。但当包含的变量足够多时,远远超过临界点时,则垃圾回收机制会循环调用,这样会导致性能问题。为了解决这个问题,在ie7发布的新版本中改变了这种方式,我的理解是这样的,在垃圾回收机制回收了较少的内存空间时,则这个临界点会加倍,如果回收后小于原先默认的临界点时,则将设为默认临界点

    临界点可以理解为根据内存分配的空间,具体一点就是256个变量、4096个对象(或数组)字面量和数组元素或64kb的字符串。

    管理内存

    一旦数据不再使用,最好通过将其值设置为null来释放引用---这个做法叫做解除引用。这一做法适用于大多数全局变量和全局对象的属性。局部变量会在它们离开执行环境时自动解除引用

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

    相关文章

      网友评论

        本文标题:【JS第13期】变量、作用域、内存等问题

        本文链接:https://www.haomeiwen.com/subject/ivgukftx.html