JavaScript学习(二):变量、作用域和内存问题

基本类型和引用类型的值

  基本类型(简单的数据段)

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

  引用类型(可能由多个值构成的对象)

  引用类型是保存在内存中的对象,JavaScript不允许直接访问内存中的位置。所以实际上是在操作对象的引用而不是实际的对象。

  1.动态的属性

  只能给引用类型值动态的添加属性。

  2.复制变量值

  因为基本类型和引用类型的访问方式不同,在复制变量的时候也会不同。

  当从一个变量向另一个变量赋值基本类型的值的时候,会创建新值,然后把值复制到此位置。

  当从一个变量向另一个变量赋值引用类型的值的时候,创建的新值是一个指向对象的指针,复制的实际上是指针,所以两个值实际上将引用同一个对象。

  3.传递参数

  ECMAScript中所有函数的参数都是按值传递的。

  在向参数传递基本类型的值时,被传递的值会复制给命名参数的局部变量,因此两者互不相关,只是拥有相同的值。

  在向参数传递引用类型的值时,会把这个值在内存中的地址复制给命名参数的局部变量,因此局部变量的变化会反应在函数外部,但不代表它是按引用访问的。

证明如下:

function setName(obj) {
    obj.name = 'Eric';
    obj = new Object();
    obj.name = 'Cherry';
}

var person = new Object();
setName(person);
alert(person.name);     //'Eric'

  4.检测类型

  typeof   

  variable instanceof constructor(如果变量是给定引用类型的实例,则返回true)

  注:因为所有的引用类型都是Object实例,所以检测引用类型值和Object构造函数时都会返回true,如果用来检测基本数据类型,始终返回false。

执行环境及作用域

  每个函数都有自己的执行环境。当执行流进入一个函数时,函数的环境就会被推入一个环境栈中。而在环境执行完成之后,栈将其环境弹出,把控制权交给之前的执行环境。

  当代码在一个环境中执行时,会创建变量对象的一个作用域链,保证对执行环境有权访问的所有变量和函数的有序访问。

  1.延长作用域链

  当执行流进入到斜面任何一个语句时,作用域链就会得到加长。

  try-catch语句的catch块;  (创建一个新的变量对象,其中包含的是被抛出的错误对象的声明)

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

  2.没有块级作用域

  条件语句中定义的变量会添加到当前执行环境,而不仅在条件语句内。

  声明变量:使用var声明的变量会添加到最接近的环境中。没有var声明的变量会被添加到全局环境中。

  查询标识符:搜索过程始终从作用域链的最前端开始逐级向后回溯,直至找到标识符为止。

垃圾收集

  1.标记清除

  给存储在内存中的所有变量加上标记,定时清理。

  2.引用计数

  跟踪每个值被引用的次数,引用次数变为0的变量就会有垃圾收集器清理。(但是由于循环引用会导致引用次数永远不会清零,即永远不会回收。)

  3.性能问题

  动态分配触发垃圾回收器的变量分配、字面量、数组元素的临界值。

  4.管理内存

  局部变量在离开它们的执行环境的时候会自动被接触引用。

  而全局变量则不会,最好的方式是数据一旦不再用,手动设置其值为null来释放其引用。

 

posted @ 2018-05-17 14:21  刁民阿准  阅读(127)  评论(0编辑  收藏  举报