由于之前在上学的时候,发现老师对着答案讲题目特别的溜。因此写文章以前,我去把查了一下闭包的概念,我将我对闭包的理解尽可能往官方解释上面凑,结果凑到最后,依旧无法用通俗的语言去解释这个概念。那么我仍是讲讲我理念上的闭包吧 。面试
我理解的闭包:一个(存于内存的)封装好的数据或方法。ajax
先讲封装好的固定数据,举个栗子:闭包
function testOne() { return 1 ; } var NumOne = testOne(); console.log(NumOne);//1
上面这个栗子就是我对闭包的一部分理解。
在说下面的话题以前,必须又得提到一个关于‘()’的理解。
个人理解上:
1 . ()的意思能够理解成 '执行';函数赋值的时候是不用带上()的,执行的时候才须要。异步
举个栗子:函数
(function test(){console.log('hello Wolrd'})();//hello world
这实际上就等同于:this
function test(){console.log('hello Wolrd'}; test();//hello world
2 . ()中能够带入参数,参数能够用于做为闭包函数执行时候的某个常量,这个常量对于外部来讲是个变量。这样说可能有点绕,那么说句广告词可能会好理解点:开局只有一把武器...那么这武器,也就是()中的参数,它在游戏开始以前是一个变量,你能够选择矛,锤...可是进入游戏以后,这把武器就不能够改了,当你执行操做的时候,选择了矛的操做矛的属性,选择了锤的只能操做锤的属性。线程
结合()的第二个特征,再说一个封装好的动态数据,代码以下:code
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
以上就是我我的对闭包的不太全面的理解,写下来主要是为本身之后作个记念,若是能帮助一些人则更为开心,有理解不足的地方但愿你们多多提意见。