闭包,顾名思义就是将某个东西包装起来,在js中则是通过包装来限定变量的作用域,可将变量分为全局变量和局部变量,当然,不仅仅是变量,也可限定函数的作用域,如内联函数等。
全局变量:
(1)在web页面中全局变量属于 window 对象。
(2)全局变量可应用于页面上的所有脚本。
(3)它的作用域是全局的。
var a = 4; function myFunction() { return a * a; }
局部变量:
(1)局部变量只能用于定义它函数内部。对于其他的函数或脚本代码是不可用的。
(2)全局和局部变量即便名称相同,它们也是两个不同的变量。修改其中一个,不会影响另一个的值。
function myFunction() { var a = 4; return a * a; }
闭包:
有权访问另一个函数作用域内变量的函数都是闭包。js的每个函数都是一个个小黑屋,它可以获取外界信息,但是外界却无法直接看到里面的内容。将变量 a 放进小黑屋里,除了 myFunction 函数之外,没有其他办法能接触到变量a,而且在函数 myFunction外定义同名的变量 a 也是互不影响的,这就是所谓的增强“封装性”。
function myFunction(){ var a = 0; function test(){ a++; console.log(a); } return test; } var test = myFunction(); test(); //控制台输出1 test(); //控制台输出2而之所以要用 return 返回函数标识 test,是因为在 myFunction 函数外部无法直接调用 test函数,所以 return test与外部联系起来。
当function里嵌套function时,内部的function可以访问外部function里的变量。
function foo(x) { var tmp = 3; function bar(y) { alert(x + y + (++tmp)); } bar(10); } foo(2)不管执行多少次,都会alert 16,因为bar能访问foo的参数x,也能访问foo的变量tmp。
function foo(x) { var tmp = 3; return function (y) { alert(x + y + (++tmp)); } } var bar = foo(2); // bar 现在是一个闭包 bar(10);上面的脚本最终也会alert 16,因为虽然bar不直接处于foo的内部作用域,但bar还是能访问x和tmp。但是,由于tmp仍存在于bar闭包的内部,所以它还是会自加1,而且你每次调用bar时它都会自加1。
实际上,在 JavaScript 中,所有函数都能访问它们上一层的作用域。
JavaScript 支持嵌套函数。嵌套函数可以访问上一层的函数变量。
总结:闭包是可访问上一层函数作用域里变量的函数,即便上一层函数已经关闭。
闭包的好处有:
1.缓存
2.面向对象中的对象
3.实现封装,防止变量跑到外层作用域中,发生命名冲突
4.匿名自执行函数,匿名自执行函数可以减小内存消耗
闭包的坏处:
1.内存消耗
通常来说,函数的活动对象会随着执行期上下文一起销毁,但是,由于闭包引用另外一个函数的活动对象,因此这个活动对象无法被销毁,这意味着,闭包比一般的函数需要更多的内存消耗。尤其在IE浏览器中需要关注。由于IE使用非原生javascript对象实现DOM对象,因此闭包会导致内存泄露问题。
2.性能问题
使用闭包时,会涉及到跨作用域访问,每次访问都会导致性能损失。