一、闭包:
概念:闭包实际上就是一个函数,与一般函数不同的是它能访问其他函数里的变量。(另一个特点就是被内部函数访问的外部函数的变量可以保存在外部函数作用域内而不被回收。即闭包可以维持函数内局部变量,使其得不到释放。)
变量分为全局变量和局部变量,在js中:函数内部可以直接读取全局变量,但是在函数外部无法读取函数内部的局部变量。但是有时需要读取到函数内部的局部变量,这时通常的做法就是在改函数内部再定义一个函数,新定义的函数是有能力访问外部函数中的变量的,此时就引入了闭包的概念。
由于在javascript中,只有函数内部的子函数才能读取局部变量,所以说,闭包可以简单理解成“定义在一个函数内部的函数“。
function f1(){
var a=100;
function f2(){
alert(n); // 100
}
} 这里闭包函数f2能够访问到f1中定义的局部变量n;
注意点:
1、由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
2、闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。
二、作用域链和垃圾回收机制:
作用域:全局、局部(函数)、eval
js中是没有块级作用域的,所以for()内和外定义的都是全局作用域。
局部作用域:利用局部作用域做封装
(function(){
var a,b
})();
!function(){
var a,b;
}(); //这里实际上是将其变成函数表达式
闭包中的作用域链:变量在作用域中的查找方式是顺着作用域链往上查找的。
当函数被调用时:
先创建一个执行环境(execution context),及相应的作用域链;
将arguments和其他命名参数的值添加到函数的活动对象(activation object)ao;
作用域链:当前函数的活动对象优先级最高,外部函数的活动对象次之,外部函数的外部函数的活动对象依次递减,直至作用域链的末端--全局作用域。优先级就是变量查找的先后顺序;