为了账号安全,请及时绑定邮箱和手机立即绑定

关于闭包封装变量的问题

关于闭包封装变量的问题

德玛西亚99 2019-05-23 18:57:06
这个是闭包封装变量的例子:functionisFirstLoad(){//查询是否是第一次输入函数debugger;var_list=[];returnfunction(id){if(_list.indexOf(id)>=0){returnfalse;}else{_list.push(id);returntrue;}};}varfirstLoad=isFirstLoad();console.log(firstLoad(10));console.log(firstLoad(10));console.log(firstLoad(20));不明白_list为什么是私有的,firstLoad(10)在传参的时候直接进到了function(id)吗?为啥不是进到isFirstLoad()啊,所以也不明白为什么可以传进来参数我按照我以前的思路改成了这个,就不能实现函数的功能了,也不懂其中的原因:functionisFirstLoad(id){//debugger;var_list=[];if(_list.indexOf(id)>=0){returnfalse;}else{_list.push(id);returntrue;}}//使用console.log(isFirstLoad(10));console.log(isFirstLoad(10));console.log(isFirstLoad(20));这样的话,全是ture,并不是很懂为什么不起作用
查看完整描述

2 回答

?
慕沐林林

TA贡献2016条经验 获得超9个赞

这是一个典型的闭包问题!讲闭包,那么就很有必要说一下变量作用域。JavaScript有两种作用域:全局作用域和函数作用域。
varlist=[true,false];
functionisFirstLoad(){
console.log(list);
}
isFirstLoad();//[true,false]
上面代码中,函数isFirstLoad可以读取全局变量list。
functionisFirstLoad(){
varlist=[true,false];
}
console.log(list);//UncaughtReferenceError:listisnotdefined
上面代码中,函数isFirstLoad内部声明的变量list,在函数外部是无法读取的。
由于种种因素,我们不得不需要函数内的局部变量,这可怎么办?设计之初,办法就帮我们想好了,就是在函数的内部,再定义一个函数。
functionisFirstLoad(){
varlist=[true,false];
functioninnerIsFirstLoad(){
console.log(list);
}
returninnerIsFirstLoad;
}
varfirstLoad=isFirstLoad();
firstLoad();//[true,false]
上面代码中,函数innerIsFirstLoad就在函数isFirstLoad内部,这时isFirstLoad内部的所有局部变量,对innerIsFirstLoad都是可见的,但是innerIsFirstLoad内部的局部变量,对isFirstLoad就是不可见的,这就是JavaScript语言特有的”链式作用域”结构,子对象会一级一级地向上寻找所有父对象的变量,所以,父对象的所有变量,对子对象都是可见的,反之则不成立。
注意:这里函数isFirstLoad的返回值是函数innerIsFirstLoad,由于innerIsFirstLoad可以读取isFirstLoad的内部变量,所以就可以在外部获得isFirstLoad的内部变量了。其中函数innerIsFirstLoad就是闭包,即能够读取其他函数内部变量的函数。由于在JavaScript语言中,只有函数内部的子函数才能读取内部变量,因此可以把闭包简单理解成定义在一个函数内部的函数。闭包最大的特点,就是它可以记住生成的环境,比如innerIsFirstLoad记住了它生成的环境isFirstLoad,所以从innerIsFirstLoad可以得到isFirstLoad的内部变量。在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。
闭包的作用很多,比较常用的几个:
可以读取函数内部的变量,并将这些变量始终保持在内存中
封装私有属性和私有方法
废话说得有点多,请耐心读完。回到您的问题:问题一:_list为什么是私有的?因为_list在函数isFirstLoad内部,函数外部访问不到的!
functionisFirstLoad(){//查询是否是第一次输入函数
debugger;
var_list=[];
returnfunction(id){
if(_list.indexOf(id)>=0){
returnfalse;
}else{
_list.push(id);
returntrue;
}
};
}
console.log(_list);//UncaughtReferenceError:_listisnotdefined
问题二:firstLoad(10)在传参的时候直接进到了function(id)吗?仔细分析示例代码,函数isFirstLoad的返回值其实是一个匿名函数,如果这样不好理解,咱们来改造下:
functionisFirstLoad(){//查询是否是第一次输入函数
var_list=[];
functioninnerIsFirstLoad(id){
if(_list.indexOf(id)>=0){
returnfalse;
}else{
_list.push(id);
returntrue;
}
};
returninnerIsFirstLoad;
}
varfirstLoad=isFirstLoad();
console.log(firstLoad(10));
console.log(firstLoad(10));
console.log(firstLoad(20));
函数isFirstLoad的返回值为函数innerIsFirstLoad,即isFirstLoad()运行结果为innerIsFirstLoad,在这里我们将它赋值给变量firstLoad。在这里函数innerIsFirstLoad就是一个闭包,它可以记住生产的环境为函数isFirstLoad,并可以访问函数局部变量_list,同时将_list始终保持在内存中,通过闭包,_list的状态被保留了,每一次调用都是在上一次调用的基础上进行计算,所以会出现true,false,true的结果。
最后您按之前的思路改写的,只是普通函数调用,并没有内存等之说,所有每次都是一样的结果!最最后祝您新年快乐!
                            
查看完整回答
反对 回复 2019-05-23
?
慕哥6287543

TA贡献1831条经验 获得超10个赞

isFirstLoad返回的是function(id){},又有如下代码
varfirstLoad=isFirstLoad();
因此firstLoad就是function(id){}
                            
查看完整回答
反对 回复 2019-05-23
  • 2 回答
  • 0 关注
  • 391 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号