执行环境和作用域
一.全局变量和局部变量
每个执行环境都有与之关联的变量对象(变量和函数存储在这里),全局执行环境是最外围的执行环境,根据ECMA实现所在的宿主不同,表示的执行环境的对象也不同。在web浏览器中,全局执行环境被认为是window对象。
每个函数都有自己的执行环境,有自己对应的变量对象(arguments对象),当执行流进入一个函数时,函数的环境会被推进一个环境栈,函数执行完后,栈将其环境弹出,把控制权交给之前的执行环境。
当代码在一个环境执行的时候,会创建变量对象的作用域链。
二.延长作用域链(有点不理解延长?)
try-catch中的catch(IE8前catch捕获的错误对象被存在了执行环境的变量对象中,而不是catch语句的变量对象中,IE9修复了这问题)
with语句:
(function addUrl(){
var qs="?a=4";
with(location){
console.log("href : "+href);
//访问location的属性成功
var url=href+qs;
}
//console.log("href : "+href);
//访问location的属性失败
console.log("url : "+url);
})();
//with的变量对象中包含了location对象的所有属性和方法,这个变量对象被添加到了作用域链前端,而location的属性和函数只能在with的作用域内访问,在with之外的addUrl函数访问不到,但with之外的addUrl函数可以访问到with内新建的变量url。
(这里和“没有块作用域”的知识有矛盾,因为这里的with里面的location属性在with外面访问不到,所以with内部本身有变量对象,但是下面的知识点又提及到语句没有块作用域)
(严格模式下不允许使用with , with大量使用会影响性能)
三.没有块作用域
if else , for 等语句定义的变量会存放在最近的执行环境中,本身没有执行环境。
使用var声明的变量会自动被添加到最近的执行环境。
标识符的查询是由近到远。
内存
一.自动的垃圾收集机制
垃圾收集器会按照固定的时间间隔周期性地找出那些不再继续使用的变量,然后释放其占有的内存。
有两种方式:
标记清除(最常用,标记的方式有很多,原理一样);
引用计数(容易造成循环引用,特别是IE8及其以下的js的COM对象!);
二.管理内存
出于安全考虑,一般计算机系统分配给wed浏览器的内存数量比桌面应用程序少,所以要在有限的内存里达到更好的性能,就可以使用解除引用的方式,此时解除一个值的引用不是说自动收回所占用的内存,而是让值脱离执行环境以便垃圾收集器下次运行的时候回收。