JavaScript读书笔记(4)-变量、作用域和内存问题

1、ECMAScript数据类型分为:基本类型值和引用类型值;

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

检查对象的类型:varible instanceof constructor

Alert(person instanceof Object);

2、  执行环境和变量

每个执行环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中;

全局执行环境是最外围的一个指定环境,在web浏览器中,全局执行环境是window对象,所有的全局变量和函数都是window对象的属性和方法;代码执行完毕,环境被销毁;

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

当代码在一个环境中执行时,会创建变量对象的一个作用域链(scope chain)。它保证对执行环境有权访问的所有变量和函数的有序访问,作用域链的前端,始终都是当前执行的代码所在环境的变量对象。如果这个环境是函数,则将其活动对象作为变量对象,活动对象在最开始时只包含一个变量,即arguments对象,作用域链中的下一个变量对象来自包含环境,而再下一个变量对象则来自下一个包含环境,这样,一直延续到全局执行环境;全局执行环境的变量对象始终都是作用域链中的最后一个对象;

标识符解析是沿着作用域链一级一级地搜索标识符的过程;

(1)       延长作用域链

有些语句可以再作用域链的前端临时增加一个变量对象,该变量对象会在代码执行后被移除;

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

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

(2)       没有块级作用域

声明变量,使用var的变量会自动被添加到最接近的环境中;初始化变量时没有使用var,该变量会自动被添加到全局环境;

不声明而直接初始化变量时一个常见的错误做法,在严格模式下,初始化未经声明的变量会导致错误;

查询标识符,从作用域链的前端开始,向上逐级查询与给定名字匹配的标识符,如果在局部环境中找到,搜索停止,如果在局部环境中没找到变量,则继续沿作用域链向上搜索,搜索过程将一直追溯到全局环境的变量对象;

变量查询的代价是,访问局部变量要比访问全局变量更快;

3、  垃圾收集

(1)       JavaScript具有自动垃圾收集机制,执行环境会负责管理代码执行过程中使用的内存;

原理:找出那些不再继续使用的变量,然后释放其占用的内存,垃圾收集器会按照固定的时间间隔(或代码执行中预定的收集时间),周期性地执行这一操作;

(2)       垃圾收集器必须跟踪哪个干粮有用哪个变量没用,对于不再有用的变量打上标记,以备将来收回其占用的内存,用于标识无用变量的策略常见的有两种:标记清除和引用计数;

(3)       标记清除,当变量进入环境时,将这个变量标记为“进入环境”,当变量离开环境时,则将其标记为“离开环境”;

垃圾收集器在运行的时候会给存储在内存中的所有变量都加上标记,然后,它会去掉环境中的变量以及被环境中的变量引用的变量的标记,而在此之后再被加上标记的变量将被视为准备删除的变量,环境中的变量已经无法访问到这些变量了,最后垃圾收集器完成清除工作,销毁那些带标记的值并回收它们所占用的内存空间;大部分浏览器都是使用的这种策略;

(4)       引用计数,跟踪记录每个值被引用的次数,当声明了一个变量并将一个引用类型值赋给该变量时,引用次数加1,相反,如果包含这个值引用的变量又取得了另外一个值,则这个值的引用次数减1,当引用次数变为0时,就可以将其占用的内存空间回收回来。

存在的问题是循环引用:对象A中包含一个对象B的指针,而对象B中也包含一个指向对象A的引用;

IE中有一部分对象并不是原生的javascript对象,BOM和DOM中的对象就是使用C++以COM对象的形式实现的,而COM对象的垃圾收集机制采用的是引用计数策略。只要IE中涉及COM对象,就会存在循环引用的问题。

Var elemen=document.getElementById(“some_element”);

Var myObject=new Object();

myObject=new Object();

element.someObject=myObject;

上面代码中一个DOM元素(element)与一个原生JavaScript对象(myObject)之间创建了循环引用;

为了避免此类问题,最好是在不适用它们的时候手工断开原生javascript对象与DOM元素之间的连接;

myObject.element=null;

element.someObject=null;

(5)       垃圾收集器是周期性运行的,如果为变量分配的内存数量很客观,那么回收工作量是相当大的,确定垃圾收集的时间间隔是很重要的问题;

Javascript引擎的垃圾收集例程工作方式:触发垃圾收集的变量分配、字面和数组元素的临界值为动态修正;

管理内存,优化内存占用的最佳方式:为执行中的代码只保存必要的数据,一旦数据不再有用,最好将其设置为null来释放其引用,其实就是解除引用;这一用法适用于大多数全局变量和全局对象的属性;

上一篇:Java中生成一个唯一值的方式


下一篇:QWebView 播放网络视频