函数的闭包是个老生常谈的话题,但说起闭包,还是很难透彻的理解它的含义,在很多应用中都要使用闭包实现,要想搞明白函数闭包是什么,首先必须得明白变量的作用域。
变量的作用域
变量分为:全局变量和局部变量
1.局部变量:在函数内部声明的,不可以在函数外部使用。(本质原因:函数再被调用的时候会入栈,并且分配空间,函数内部的变量,都是在这块空间内部声明的,当函数运行完毕之后就会出栈,系统回收空间,函数内部的变量所占空间也会被回收,所以不能在函数外面使用函数内部定义的变量)
2.全局变量:在函数以外声明的。
eg1. 数组里面的两个a是同一个a。对象引用
var a = {name:"张三", age:18};
var arr = [];
arr.push(a);
arr.push(a);
// a发生变化之后,数组内部也会改变、。
a.name = "李四";
console.log(arr[0] == arr[1]);
eg2.函数t运行两次,就会有2个a。这两个a不是同一个a
var arr = [];
function t(){
var a = {name:"张三", age:18};
arr.push(a);
}
t();
t();
arr[0].name = "李四";
console.log(arr);
console.log(arr[0] == arr[1]);
eg3.执行同一次函数的时候,变量是相同的
var arr = [];
function t(){
var a = {name:"张三", age:18};
arr.push(a);
arr.push(a);
}
t();
arr[0].name = "李四";
console.log(arr);
console.log(arr[0] == arr[1]);
上面三个例子充分解释了变量作用域的区别。
函数的闭包
闭包简单来说就是函数内部的函数,闭包里面使用局部变量和函数参数的时候,用的就是外部函数的局部变量。
1.同一个函数调用两次,会返回两个函数f1,和f2。 f1和f2里面的a分别是第一次和第二次调用fn的时候生成的a。所以是两个不同的a
function fn(){
var a = 10; // 局部变量
return function(){
console.log(++a);
}
}
var f1 = fn(10);
var f2 = fn(10);
f1();
f1();
f1();
f1();
f1();
f2();
2.调用一次函数返回两个函数f1,和f2。f1和f2里面的a都是第一次调用fn的时候生成的,所以是同一个a
function fn(){
var a = 10; // 局部变量
function in1(){
console.log(++a);
}
function in2(){
console.log(++a);
}
return [in1, in2];
}
var arr = fn();
var f1 = arr[0];
var f2 = arr[1];
f1();
f1();
f1();
f1();
f1();
f2();
闭包虽然用处很大,但它的弊端也不容忽视。闭包会导致函数运行结束之后局部变量的空间不会被释放从而造成内存泄露(执行的次数越多,占用的内存越多),所以一些经常需要重复执行的代码不适合使用闭包。