闭包是js面试必问的一个问题,但对闭包一直是一知半解。
闭包的常用解释:是指有权访问另一个函数作用域中的变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量。
如果从字面上理解始终有点容易让人懵。
非闭包代码
var userName="张三";
var User=function(){
var userName="李四";
}
User();
console.log(userName);//输出张三
//那如果想访问到 李四 有啥法子呢
写个闭包就可以实现
var userName="张三";
var User=function(){
var userName="李四";
function getUserName(){
console.log(userName);//输出李四
}
return getUserName();
}
User();
看上面的代码,其实感觉不出闭包的意义,仅仅是执行了一个函数,而执行了一个打印函数域变量而已。
我们改造下
var userName="李四";
var User=function(){
var userName="李四";
function getUserName(){
return userName;
}
return getUserName;
}
var getNewName=User();
var newName=getNewName();
console.log(newName);//输出李四
//成功的在函数外,访问到User函数的局部变量
这种演示代码可能还是感觉不到闭包的价值,下面举个实用的js例子
var userNames=[
{name:"张三",age:10},
{name:"李四",age:20},
{name:"王五",age:30},
{name:"陈六",age:40}
];
var accreditUtils=(function(){
//过滤出大于20岁的用户
var oldUser=userNames.filter(function(value){
if(value.age>20){
return value;
}
});
//过滤出小于20岁的用户
var smallUser=userNames.filter(function(value){
if(value.age<20){
return value;
}
});
return {
getOldUser:function(){
return oldUser;
},
getSmallUser:function(){
return smallUser;
}
}
})();
//打印出大于20岁的用户
var oldUser=accreditUtils.getOldUser();
oldUser.forEach(function(val){
console.log(val.name);
})
这就是个典型的闭包例子,不采用闭包我们也能实现该功能,但闭包体现了面向对象的封装的概念,外部调用者只关心结果,而不关心封装过程。
代码也显得更加直观,也可以提高代码的复用度。