执行环境
所有变量(基本类型、引用类型以及函数)都存在于一个执行环境当中,这个执行环境决定了变量的生命周期,以及哪一部分代码可以访问其中的变量。
每个执行环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中。
执行环境可以划分为两类:
-
全局执行环境
全局执行环境是最外围的一个执行环境。根据ECMAScript实现所在的宿主环境不同,表示执行环境的变量对象也不一样。例如,在WEB浏览器中,与全局执行环境关联的变量对象是
windows
对象。 -
函数执行环境
每个函数都有自己的执行环境,函数执行环境的变量对象被称为活动对象,它在最开始只包含一个变量,即
arguments
对象。
作用域链
执行流每进入一个执行环境,都会创建一个作用域链。
作用域链由执行环境的变量对象组成,作用域链的前端始终是当前执行环境的变量对象,下个变量对象来自外围环境,再下一个变量对象则来自下一个外围环境,一直延续到全局执行环境的变量对象。全局执行环境的变量对象始终都是作用域链中的最后一个变量对象。
作用域链的用途是保证对执行环境有权访问的所有变量和函数的有序访问。
延长作用域链
当执行流进入try - catch
语句的catch
块或者进入with
语句,解释器就会再当前作用域链的最前端增加一个变量对象。这个变量对象是临时的,它会在语句执行完后被移除。
延长作用域链的特点是:
- 添加的变量对象是临时的,在语句执行完后将被移除
- 添加的变量对象不关联执行环境。这意味着在语句中声明的变量属于包含这些特殊语句的执行环境的变量对象。
var location = new Object();
location.href = "https://baidu.com/";
function buildUrl() {
var qs = "search?wd=%s";
with (location) {
var url = href + qs;
}
alert(url);
}
buildUrl();
全局执行环境中定义了变量location
和函数buildUrl
,函数执行环境中定义了变量qs
和url
。with
语句延长了函数执行环境的作用域链,解释器解析标识符href
会首先在变量对象location
搜所,如果没有延长作用域机制,我们无法解析href
;此外,with
语句不会创建执行环境,如果创建执行环境,当with
语句结束,变量url
将被销毁,我们无法在函数执行环境中访问,代码运行结果显然情况不是这样。
没有块级作用域
JavaScript没有块级作用域,变量的声明周期和执行环境有关。
var
操作符声明的变量,将会添加到最近的执行环境的变量对象中。
JavaScript常用的垃圾收集方式是:
- 标记清除
- 引用计数
目前,众浏览器厂商推行J的avaScript的垃圾收集方式是标记清除(旧版本IE除外)。