首页 > 代码库 > JavaScript学习笔记—— 4. 变量、作用域和内存问题

JavaScript学习笔记—— 4. 变量、作用域和内存问题

  1. ECMAScript变量可能包含两种不同数据类型的值:基本类型值和引用类型值,其中基本类型值是简单的数据段,而引用类型值指的是那些可能由多个值构成的对象;
  2. 对于5种基本类型数据:undefined, null,boolean,number和string,采用按值访问,因为可以操作保存在变量中的实际的值;
  3. 对于引用类型的值而言,JavaScript并不能直接访问内存中的位置,也就是说不能直接操作对象的内存空间,在操作对象时,实际上是在操作对象的引用而非实际的对象。
  4. 在从一个变量向另一个变量复制基本类型值和引用类型值的时候,也存在不同:
    • 如果从一个变量向另一个变量复制基本类型的值,会在变量对象上创建一个新值,然后把该值复制到为新变量分配的位置上(所以对新创建的变量的值的操作,不会影响原先的变量);
    • 当从一个变量向另一个变量复制引用类型的值时,同样也会将存储在变量对象中的值复制一份放到为新变量分配的空间中。实际上这个值的副本是一个指针,指向存储在堆中的一个对象,所以结果是两个变量实际上引用同一个对象,所以改变其中一个变量,将对另一个变量也产生同样的影响。
  5. ECMAScript中的所有函数的参数传递,都是按值传递的。即:把函数外部的值复制给函数内部的参数。基本类型值的传递如同基本类型变量的复制一样,而引用类型值的传递,则如同引用类型变量的复制一样。
  6. instanceof: result  =  variable instanceof constructor;
    • alert(person instanceof Object); //变量person是Object么
    • alert(person instanceof Array); //变量person是Array么
  7. 作用域链(scope chain):保证对执行环境有权访问的所有变量和函数的有序访问。作用域链的前端,始终是当前执行的代码所在环境的变量对象,如果这个环境是函数,则将其活动对象(activation object)作为变量对象。活动对象在最开始时只包含一个变量,即arguments对象。下一个变量对象来自包含(外部)环境,而再下一个对象则来自下一个包含环境。这样,一直延续到全局执行环境;全局执行环境的变量对象始终都是作用域链中的最后一个对象。
  8. 使用var声明的变量会自动添加到最接近的环境中。
  9. 基本类型值和引用类型值具有以下特点:
    • 基本类型值在内存中占据固定大小的空间,因此被保存在栈内存中;
    • 从给一个变量向另一个变量复制基本类型的值,会创建这个值的一个副本;
    • 引用类型值是对象,保存在堆内存中;
    • 包含引用类型值的变量实际上包含的并不是对象本身,而是一个指向这个值的一个副本;
    • 从一个变量向另一个变量复制引用类型的值,复制的其实是指针,因此两个变量最终都指向同一个对象;
    • 确定一个值是哪一种基本类型可以使用typeof操作符,而确定一个值是哪一种引用类型可以使用instanceof操作符、
  10. 关于执行环境:
    • 执行环境有全局执行环境(也称为全局环境)和函数执行环境之分;
    • 每次进入一个新执行环境,都会创建一个用于搜索变量和函数的作用域链;
    • 函数的局部环境不仅有权访问函数作用域中的变量,而且有权访问其包含(父)环境,乃至全局环境;
    • 全局环境只能访问在全局环境中定义的变量和函数,而不能直接访问局部环境中的任何数据;
    • 变量的执行环境有助于确定应该何时释放内存;
  11. 关于JavaScript的垃圾收集例程:
    • 离开作用域的值将被自动标记为可以回收,因此在垃圾收集期间被删除;
    • “标记清除”是目前主流的垃圾收集算法,这种算法的思想是给当前不使用的值加上标记,然后在回收内存;
    • “引用计数”垃圾收集算法是跟踪记录所有值被引用的次数,JavaScript引擎目前都不再使用这种算法;
    • 解除变量的引用(比方说:var globalVar = createdVar(“things”); globalVar = null;)有助于消除循环引用的现象,并且有益于垃圾收集。为了确保有效地回收内存,应该及时接触不再使用的全局对象、全局对象属性以及循环引用变量的引用。
 
 
 
 
 
 
 
 
 
 
 
 

JavaScript学习笔记—— 4. 变量、作用域和内存问题