闭包:一个(存于内存的)封装好的数据或方法。
先讲封装好的固定数据,举个例子:
function testOne() {
return 1 ;
}
var NumOne = testOne();
console.log(NumOne);//1
上面这个栗子就是我对闭包的一部分理解。
在说下面的话题之前,必须又得提到一个关于‘()’的理解。
我的理解上:
1 . ()的意思可以理解成 '执行';函数赋值的时候是不用带上()的,执行的时候才需要。
举个栗子:
(function test(){console.log('hello Wolrd'})();//hello world
这实际上就等同于:
function test(){console.log('hello Wolrd'};
test();//hello world
2 . ()中可以带入参数,参数可以用于作为闭包函数执行时候的某个常量,这个常量对于外部来说是个变量。这样说可能有点绕,那么说句广告词可能会好理解点:开局只有一把武器...那么这武器,也就是()中的参数,它在游戏开始之前是一个变量,你可以选择矛,锤...但是进入游戏之后,这把武器就不可以改了,当你执行操作的时候,选择了矛的操作矛的属性,选择了锤的只能操作锤的属性。
结合()的第二个特征,再说一个封装好的动态数据,代码如下:
var spear = {operation:'刺'};
var hammer = {operation:'挥'};
function con_opera(t) {
return (t.operation);
}
console.log(con_opera(spear)); //刺
console.log(con_opera(hammer)); //挥
3.()的参数可以为多个,包括this,window,event等。
结合()的第三个特征,再端盘关于封装好的方法的栗子:
function plusFn(a,b){
console.log(a+b);
}
plusFn(3,4);//7
关于我对闭包的用途的理解 。
1.面向对象。
如果说现在现在有很多个玩家进游戏选角色的时候要捏人,如果从过程上去处理,那无疑是不够灵活的。
如果从对象上处理呢?
①.便于复用:
捏头(头部属性);捏身子(身子属性);捏手(手部属性);捏腿(腿部属性);
这样的话,只要写四个方法,就可以拼接成一个捏人的方法。而且可以重复使用这套方法,构成结构的多样性。
②.便于代码维护:
如果想要在身上捏对翅膀的话,完全可以再多加一个捏翅膀(翅膀属性);
2.异步处理。
因为闭包使用的是参数,而不闭包使用的是变量,之前解释过,参数为函数内部的常量,这个值在调用闭包的时候已经设置好,不会随着外界变量的改变而改变。
还有个是个人的习惯问题,我更喜欢的是写好一个方法,然后到处使用,尤其是ajax的时候,得到参数的处理方法,success的时候 fun(返回值),error的时候 fun(默认值),而且由于js的单线程多进程,频繁切换进程但同一进程却是按照顺序执行,这样的话,将方法闭包放入一个进程里面可以既方便又有效地避免异步引发的bug。
3.方便回调
从前有座山,山上有座庙,瞄里有个老和尚,老和尚给小和尚讲故事:。。。
这就是无限循环就是个回调函数。
(function test(){
console.log('从前有座山,山上有座庙,瞄里有个老和尚,老和尚给小和尚讲故事:');
test();
})();
闭包题的分析:
这里从网上找了俩道比较经典的面试题,因为我实在也不知道它们初始出处是哪里,原谅我没法写引用地址。
1.
for(var i = 1; i <= 5; i++) {
setTimeout( function () {
console.log(i);
}, 1000 );
} //5 5 5 5 5
改写一下:
function test(t){
setTimeout( function () {
console.log(t);
}, 1000 );
}
for(var i = 1; i <= 5; i++) {
test(i);
} //1,2,3,4,5
这个就是异步的问题,如果使用闭包,闭包被调用的时候,console.log()分配的参数则是1,2,3,4,5这五个常量。而不闭包,则是瞬间去给五个console.log()分配了变量i,而i在内存中是一个变量,在setTimeout设定的时间到达时,已经是5了,这也是为什么一下子输出5个5的原因。
2.
function fun(n,o) {
console.log(o)
return {
fun:function(m){
return fun(m,n);
}
};
}
var a = fun(0); a.fun(1); a.fun(2); a.fun(3);
var b = fun(0).fun(1).fun(2).fun(3);
var c = fun(0).fun(1); c.fun(2); c.fun(3);
说实话,第一次做这题的时候,感觉在坐升降机,又像在看无限放大的漩涡。
return的意思为返回值,返回值的意思就一个函数的处理结果:加水(糖){return ‘糖水’}
a = fun(0);//fun(0,o),此时o为undefined,
所以console.log 一个 undefined
并
return {fun:function(m)}
则
a = {
fun:function(m){
return fun(m,0);
}
}
a.fun(1) = function(1){
return fun(1,0);
};
fun(1,0) = {
console.log(0);
return {
fun:function(m)
}
};//所以会console.log一个0
a.fun(2)与a.fun(3)同a.fun(1);
关于b fun(0).fun(1) == a.fun(1)//到这层为止,请参照a.fun(1)的解释。所以会console.log undefined,0;
fun(0).fun(1).fun(2)//这层
fun(0).fun(1) = {
console.log(0);
return{
fun:function(m){
return fun(m,1);
}
}
}则fun(0).fun(1).fun(2) = fun(2,1); //运行到fun(0).fun(1).fun(2)这层
fun(2,1) = {
console.log(1);
return {
fun:function(m)
{
return fun(m,2);
}
}
}//所以会console.log一个1
则fun(0).fun(1).fun(2).fun(3) = fun(3,2);//同理于fun(2,1),所以会console.log一个2
//那么c这边就好解决的多了。
c = fun(0).fun(1) //类似于a.fun(1); 所以会console.log undefined,0;
c.fun(2)与c.fun(3)//参考b 的fun(0).fun(1).fun(2) ,所以会console.log 1,1.
//所以最后答案为 undefined,0,0,0;undefined,0,1,2;undefined,0,1,1
以上就是我个人对闭包的不太全面的理解,写下来主要是为自己以后做个纪念,如果能帮助一些人则更为开心,有理解不足的地方希望大家多多提意见。
转自:https://segmentfault.com/a/1190000010604209
作者 : lackdata
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
如果文章不错,请转发的朋友圈!
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
==========阅读原文==========