理解闭包
闭包是创建一个函数的时候允许在这函数里可以访问并且操作函数之外的变量所创建的作用域。
随处可见的闭包
var name = 'cher'; //一个全局变量
function fn() { //声明一个全局函数
console.log(name); //cher 在这个函数里面访问外面的全局变量
}
fn();//在这函数里面可以访问到函数外的变量形成了简单的闭包
一个神奇的闭包
var name = 'cher'; //创建一个全局变量
var innerFn;
function outFnHandler() { //创建一个全局函数
var outname = 'xiaoming'; //全局函数下的一个变量
function innerFnHandler() { //一个内部函数
console.log(name); //cher
console.log(outname); // xiaoming
}
innerFn = innerFnHandler;
}
outFnHandler(); //执行这个全局函数的时候,把内部函数放到innerFn变量上
innerFn(); //在执行这个内部函数,必须要执行完全局函数后才能执行innerFn函数
在这里outFnHandler已经执行完毕,作用域不在了,为什么内部函数还可以访问到outname变量?
因为闭包,创建innerFnHandler的时候也创建了一个闭包,闭包里包含了这个声明的函数,还包含了这个声明的函数作用域下的所有变量,
所有即使作用域消失,但是通过闭包还是可以访问outname
看看那些东西是闭包可以访问的
var name = 'cher'; //创建一个全局变量
var innerFn;
function outFnHandler() { //创建一个全局函数
var outname = 'xiaoming'; //全局函数下的一个变量
function innerFnHandler(age) { //一个内部函数
console.log(name); //cher
console.log(outname); // xiaoming
console.log(age); //7
console.log(sex); //男
}
innerFn = innerFnHandler;
}
console.log(sex); //undefined
var sex = '男';
outFnHandler(); //执行这个全局函数的时候,把内部函数放到innerFn变量上
innerFn(7); //传递一个实参给内部函数
这里可以看得出给内部函数传递一个参数过去是可以访问的,作用域之外的所有变量不管前后都是可以访问的,所以可以访问到sex
闭包的作用
1、可以封装一些东西作用私有变量
function Fn() { //声明一个构造器
var name = 0; //构造器里有一个变量name
this.getName = function () { //创建一个获取这个name变量的方法
return name;
}
this.setName = function () { // 创建一个设置name变量的方法
name++ ;
}
}
var fn = new Fn();
fn.setName(); //这样就只能通过setName来设置这个变量
console.log(fn.getName()); //用getName 来获取这个变量
在这里我们就只能通过构造器的俩个方法来获取或者设置构造器里的变量,就像面向对象语言里面的私有变量了。
2、回调
回调函数是一个在需要的时候可以执行的一种函数,回调函数就是一个闭包,通常回调函数就会访问外面的闭包
function outFn(fn) { //创建一个全局函数
var name = 'cher'; //在这个全局函数里创建一个变量name
console.log(name); //cher
fn(name); //使用回调可以访问这个全局函数里的变量name
}
outFn(function (sex) {
console.log(sex); //cher
});
在这里的回调就可以访问外部的变量,也避免了使用全局变量