执行环境及作用域
名词解释
执行环境(作用域): 定义了变量或函数有权访问的其他数据,决定它们各自的行为。全局作用域被认为是window对象(应用程序退出时销毁),函数作用域可通过作用域链访问所有的外部环境,但外部环境无法访问内部环境中任何变量和函数。
作用域链: 当前执行环境的变量对象–>外部环境–>下一个外部环境…–>全局执行环境。
延长作用域链(?)
有些语句可以在作用域链的前端临时增加一个变量对象,该对象会在代码执行后被移除。
- with语句会将指定对象添加到作用域链中
- catch语句会创建一个新的变量对象,其中包含的是被抛出的错误对象的声明。
个人理解: 在当前执行环境中引入特定对象,代码执行完毕后销毁(相当于块级作用域?)。
没有块级作用域
if、for、with等语句内部定义的变量在代码执行完毕后仍能被访问。
声明变量
使用var声明的变量自动被添加至最接近的环境中,未经声明的变量被添加至全局环境中(严格模式下会报错)。
function add(num1, num2) {
var sum = num1 + num2;
ans = sum;
return sum;
}
var result = add(1, 2);
alert(ans); //3
alert(sum); //报错
查询标识符
如果局部环境中存在同名标识符,则不会使用父环境中的标识符。
var name = "Lou";
function getName() {
var name = "Danke";
return name;
}
alert(getName()); //"Danke"
访问局部变量要比访问全局变量速度更快,但 JavaScript 引擎的优化使得该差别可以忽略不计。
垃圾收集
JavaScript具有自动垃圾收集机制。为此,垃圾收集器会按照固定的时间间隔(或代码中预定的收集时间),周期性地找出不再继续使用的变量并释放其内存。用于标识无用变量的策略通常有两种:
-
标记清除
标记-清除两阶段:进入环境/离开环境
-
引用计数(COM对象,不常用)
跟踪记录每个值被引用的次数,。声明变量并将引用类型值赋给该变量时,值的引用次数为1;同一个值被赋给另一变量时,引用次数加1;引用变量舍弃该值后,引用次数减1。引用次数为0的值所占用的内存会被释放。
存在循环引用(对象A包含指向对象B的指针,对象B也包含指向对象A的指针)现象,需要手动断开连接(赋值null)。
浏览器的可用内存数量通常要比桌面应用程序少,该限制不仅影响变量分配内存,也会影响调用栈及在一个线程中能够同时执行的语句数量。因此,确保占用最少的内存可以让页面获得更好的性能。对于大部分全局变量,一旦数据不再有用,最好通过将其值设置为null来释放其引用(即解除引用)。 不过,解除引用并不意味着自动回收该值所占用的内存,而是让值脱离执行环境以便回收。