学习javascript基础知识系列第四节 - 闭包
通过一段代码学习javascript基础知识系列
闭包的含义:
Wikipedia:在计算机科学中,闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。
百度百科:闭包是可以包含自由(未绑定到特定对象)变量的代码块;这些变量不是在这个代码块内或者任何全局上下文中定义的,而是在定义代码块的环境中定义(局部变量)。“闭包” 一词来源于以下两者的结合:要执行的代码块(由于自由变量被包含在代码块中,这些自由变量以及它们引用的对象没有被释放)和为自由变量提供绑定的计算环境(作用域)。在 Scala、Scheme、Common Lisp、Smalltalk、Groovy、JavaScript、Ruby、 Python和Lua,objective c 等语言中都能找到对闭包不同程度的支持。
在编程领域我们可以通俗的说:子函数可以使用父函数中的局部变量,这种行为就叫做闭包!
为了理解闭包,看下面一段代码:
[javascript]
function test(){
var n = 1;
var increaseAndShow = function(){
if(window.console&&window.console.log){
console.log(++n);
}
else{
alert(++n);
}
}
return increaseAndShow;
}
var a = test();
a();
//输出2
a();
//输出3
上面这段代码,最主要的一点就是函数test返回了一个函数increaseAndShow,increaseAndShow函数中对局部变量n进行了前置加操作。
创建一个变量a=test()后,a()每次执行,输出的值都会增加1,按照前面通俗的说法:子函数可以使用父函数中的局部变量,这种行为就叫做闭包!
写出这种让新手疑惑的方法并不是为了显示高深,闭包有以下特点:
1.js中对象,使用this.xx添加的对象属性是可以直接访问的,因而在某些场合是不安全的,使用闭包操作局部变量就可以解决这个问题,只有通过函数去访问局部变量,而不能直接访问,因而可以避免某些不安全的情况,总之,作用就是保护函数内的变量安全。
2.在内存中维持一个变量。由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
原理:
在Javascript中,如果一个对象不再被引用,那么这个对象就会被GC回收。如果两个对象互相引用,而不再被第3者所引用,那么这两个互相引用的对象也会被回收。因为函数a被b引用,b又被a外的c引用,这就是为什么函数a执行后不会被回收的原因。
闭包的用法 - 返回对象
[javascript
function test(){
var n = 1;
function max(a,b){return a>b?a:b;}
function increaseAndShow(){
if(window.console&&window.console.log){
console.log(++n);
}
else{
alert(++n);
}
}
return {
name:'闭包',
max:max,
show:increaseAndShow
};
}
上面的代码返回了一个对象,对象引用了两个方法。
可以使用var a = test();
然后就可以使用a.max(1,2)调用方法,a.show()多次执行结果会一直递增下去。
使用闭包还可以写出一些怪异的代码,如下:
[javascript]
var add = function(a){
return function(b){
return function(c){
return a+b+c;
}
}
}
add(1)(2)(3);
//结果6
function addTemp(a){
var temp = a;
return function(b){
return temp+b;
}
}
var b = addTemp(10);
b(13);
//结果23
第一个add没太大意义,第二个addTemp在某些情况下是有一定用途的。
学习闭包,重点在于理解函数对局部变量的使用。
另外闭包中的this仍然是作为函数执行时指向window,作为方法时,指向对象自己。
补充:web前端 , JavaScript ,